Giter Site home page Giter Site logo

morpho-blue-oracles's Introduction

Morpho Blue Oracles

Morpho Blue Oracles are contracts that can be used as oracles for markets on Morpho Blue. The oracles implement the IOracle interface defined in IOracle.sol: they return the price of 1 asset of collateral token quoted in 1 asset of loan token.

MorphoChainlinkOracleV2

The MorphoChainlinkOracleV2 is an oracle that uses Chainlink-interface-compliant feeds to provide price data.

This oracle handles the following cases among others (let's say that our pair is A/B):

  • A/B is a feed (typically, stETH/ETH).
  • B/A is a feed (typically, ETH/USDC).
  • A/C and B/C are feeds (typically, stETH/ETH and USDC/ETH).
  • A/C, C/D and B/D are feeds (typically, WBTC/BTC, BTC/USD, USDC/USD).
  • A/D, and B/C, C/D are feeds (typically, USDC/USD, WBTC/BTC, BTC/USD).
  • A/C, C/D and B/E, E/D are feeds.
  • A/C and C/B are feeds (typically, WBTC/BTC and BTC/ETH).
  • A'/C and B/C are feeds, and there is an exchange rate between A and A'. (typically A=sDAI and A'=DAI).

Deploy an Oracle

To deploy a MorphoChainlinkOracleV2 on Ethereum, it is highly recommended to use the factory MorphoChainlinkOracleV2Factory. To do so, call the createMorphoChainlinkOracleV2 function with the following parameters:

  • baseVault: The ERC4626 token vault for the base asset.
  • baseVaultConversionSample: A sample amount for converting base vault units.
  • baseFeed1, baseFeed2: Chainlink-interface-compliant data feeds for the base asset.
  • baseTokenDecimals: Decimal precision of the base asset.
  • quoteVault: The ERC4626 token vault for the quote asset.
  • quoteVaultConversionSample: A sample amount for converting quote vault units.
  • quoteFeed1, quoteFeed2: Chainlink-interface-compliant data feeds for the quote asset.
  • quoteTokenDecimals: Decimal precision of the quote asset.
  • salt: A unique identifier to create deterministic addresses for deployed oracles.

Warning: If there is an ERC4626-compliant vault for baseVault or quoteVault, the baseTokenDecimals or quoteTokenDecimals are still the decimals of the underlying asset of the vault, and not the decimals of the Vault itself. E.g: for a MetaMorpho WETH vault, as baseVault, the baseTokenDecimals is 18 as WETH has 18 decimals.

Addresses

The address on Ethereum of this factory is 0x3A7bB36Ee3f3eE32A60e9f2b33c1e5f2E83ad766.

Examples

Below are the arguments to fill for the creation of the WETH/USDT oracle:

"baseVault": "0x0000000000000000000000000000000000000000",
"baseVaultConversionSample": 1,
"baseFeed1": "0x0000000000000000000000000000000000000000",
"baseFeed2": "0x0000000000000000000000000000000000000000",
"baseTokenDecimals": 18,
"quoteVault":"0x0000000000000000000000000000000000000000",
"quoteVaultConversionSample": 1,
"quoteFeed1": "0xEe9F2375b4bdF6387aa8265dD4FB8F16512A1d46",
"quoteFeed2": "0x0000000000000000000000000000000000000000",
"quoteTokenDecimals": 6,
"salt": "<user-defined value used to make the address unique>",

and for the sDAI/USDC oracle:

"baseVault": "0x83F20F44975D03b1b09e64809B757c47f942BEeA",
"baseVaultConversionSample": 1000000000000000000,
"baseFeed1": "0xAed0c38402a5d19df6E4c03F4E2DceD6e29c1ee9",
"baseFeed2": "0x0000000000000000000000000000000000000000",
"baseTokenDecimals": 18,
"quoteVault": "0x0000000000000000000000000000000000000000",
"quoteVaultConversionSample": 1,
"quoteFeed1": "0x8fFfFfd4AfB6115b954Bd326cbe7B4BA576818f6",
"quoteFeed2": "0x0000000000000000000000000000000000000000",
"quoteTokenDecimals": 6,
"salt": "<user-defined value used to make the address unique>",

and for the wstETH/ETH oracle:

"baseVault": "0x0000000000000000000000000000000000000000",
"baseVaultConversionSample": 1,
"baseFeed1": "0x905b7dAbCD3Ce6B792D874e303D336424Cdb1421",
"baseFeed2": "0x86392dC19c0b719886221c78AB11eb8Cf5c52812",
"baseTokenDecimals": 18,
"quoteVault": "0x0000000000000000000000000000000000000000",
"quoteVaultConversionSample": 1,
"quoteFeed1": "0x0000000000000000000000000000000000000000",
"quoteFeed2": "0x0000000000000000000000000000000000000000",
"quoteTokenDecimals": 18,
"salt": "<user-defined value used to make the address unique>",

WstETH/stETH Exchange Rate Adapter

A specific implementation, the WstEthStEthExchangeRateChainlinkAdapter, provides the exchange rate between wstETH and stETH as a Chainlink-interface-compliant feed.

This adapter is deployed on the Ethereum Mainnet at the address 0x905b7dAbCD3Ce6B792D874e303D336424Cdb1421.

Getting Started

Install dependencies: forge install

In a .env file, set ETH_RPC_URL to the URL of an Ethereum provider.

Run test: forge test

Audits

All audits are stored in the audits' folder.

License

Morpho Blue Oracles are licensed under GPL-2.0-or-later, see LICENSE.

morpho-blue-oracles's People

Contributors

adhusson avatar jean-grimal avatar julien-devatom avatar mathisgd avatar merlinegalite avatar qgarchery avatar rubilmax avatar tomrpl avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

morpho-blue-oracles's Issues

Refactor testing setup

I don't like this because nothing ensures the RPC URL points to mainnet, whereas the setup in morpho-blue-bundlers does
But it's something for later, non-blocking

Originally posted by @Rubilmax in #1 (comment)

Add missing comments

  • Why min/max on aggregator are not checked
  • Why no stale period
  • Why fallback oracle

Add README.md

Add how to setup the repo notably setting ETH_RPC_URL in a .env file

Discuss stale period

As a reference:

On my side I'd be in favor of implementing a stale period check of 36 hours or 48 hours. This is a safe margin I think. We can safely say that after this period the price feed is stale

Chainlink checks

Things to look at:

  1. negative answer
  2. min max bounds
  3. time out (stale price)
  4. (L2) sequencer timelock after down time

expectedSupplyAssets behaving differenly locally and in CI-CD pipeline (gitlab)

I'm using hardhat to fork the mainnet and run unittest for my api calls and I got an issue when testing the function

export async function getLoanTokenSupplied(
  publicClient: PublicClient,
  marketParam: MorphoMarketParams,
  userAddress: EOAAddress,
): Promise<bigint> {
  return await publicClient.readContract({
    address: leverosAddress,
    abi: LeverosMorphoBlueAbi,
    functionName: 'supplyAssetsUser',
    args: [ marketParam, userAddress]
  })
}

my test as follow

  it('retrieves the amount of loanToken a given user has supplied', async function () {
    await loadFixture(deployLeveros);
    const { userWallet } = await loadFixture(setUpLeveros);
    const publicClient = await hre.viem.getPublicClient();

    const amountSuppliedByUser = await getLoanTokenSupplied(
      publicClient,
      getMorphoMarketParam(leverosParam),
      userWallet.account!.address as EOAAddress,
    )
    expect(amountSuppliedByUser).to.approximately(AMOUNT_LOAN_TOKEN_SUPPLIED, BigInt(147498892026))
  });

The test passes when I run it locally npx hardhat test but the same test fails consistently when running in my CI-CD pipeline on Gitlab, with an assertion error:

AssertionError: expected 10000000147498892026 to equal 10000000000000000000

the morpho function supplyAssetsUser used in that test says in its docstring says:

Returns the expected supply assets balance of user on a market after having accrued interest

Would that consistent 147498892026 discrepancy comes from that accrues interest calculation which somehow behave differently locally and in my CI-CD docker environement?

here is my .gitlab-ci.yml content

include:
  - template: Security/SAST.gitlab-ci.yml


default:
  tags:
    - local_runner
  before_script:
    - corepack enable
    - corepack prepare pnpm@latest-8 --activate
    - pnpm config set store-dir .pnpm-store

stages:
  - build_container
  - lint
  - install_project
  - test
  - security

variables:
  GIT_SUBMODULE_STRATEGY: recursive
  CI_REGISTRY: registry.gitlab.com
  TEST_IMAGE: $CI_REGISTRY/leveros1/leveros-v1-core/node20-forge:latest
  ETH_RPC_URL: "https://cloudflare-eth.com"

sast:
  before_script: []
  # You can override the included template(s) by including variable overrides
  # SAST customization: https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings
  # Secret Detection customization: https://docs.gitlab.com/ee/user/application_security/secret_detection/#customizing-settings
  # Dependency Scanning customization: https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings
  # Container Scanning customization: https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings
  # Note that environment variables can be set in several places
  # See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence
  stage: security

build_and_push:
  when:
    manual
  before_script: []
  image: docker:latest
  services:
    - docker:dind
  stage: build_container
  script:
    - echo "Building Docker image..."
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
    - docker build -t $TEST_IMAGE -f test/Dockerfile .
    - docker push $TEST_IMAGE

lint-solhint:
  stage: lint
  image: $TEST_IMAGE
  script:
    - pnpm install
    - pnpm run lint

.install:
  script:
    - forge --version
    - pnpm i
    - rm -rf lib/*
    - forge install foundry-rs/forge-std --no-commit
    - forge install morpho-org/morpho-blue --no-commit
    - forge install morpho-org/morpho-blue-oracles --no-commit
    - forge update morpho-org/morpho-blue-oracles # no idea why it doesn't fetch that latest version. updated today by morpho, some CDN caching?
    # cmd 'forge install OpenZeppelin/[email protected] --no-commit' works in local but not in CI. workaround: manually checkout the version in the submodule
    # downgrade morpho-blue-oracles's openzeppelin to accommodate Morpho pinned to solc 0.8.19. temporary? workaround for issue: https://github.com/morpho-org/morpho-blue/issues/672#issuecomment-1978740721
    - (cd lib/morpho-blue-oracles/lib/openzeppelin-contracts && git fetch --tags && git checkout v4.9.6)
    - forge install OpenZeppelin/openzeppelin-contracts --no-commit
    - (cd lib/openzeppelin-contracts && git fetch --tags && git checkout v4.9.6)

test-forge:
  stage: test
  image: $TEST_IMAGE
  script:
    - !reference [.install, script]
    - forge test

test-hardhat:
  stage: test
  image: $TEST_IMAGE
  script:
    - !reference [.install, script]
    - npx hardhat test

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.