Giter Site home page Giter Site logo

morpho-org / morpho-blue Goto Github PK

View Code? Open in Web Editor NEW
91.0 8.0 30.0 5.56 MB

๐ŸŸฆ Morpho Blue Protocol

Home Page: https://morpho.org

License: Other

Shell 0.07% TypeScript 2.85% Solidity 74.84% Ruby 21.87% Python 0.37%
defi lending morpho primitive protocol

morpho-blue's Introduction

Morpho Blue

Morpho Blue is a noncustodial lending protocol implemented for the Ethereum Virtual Machine. Morpho Blue offers a new trustless primitive with increased efficiency and flexibility compared to existing lending platforms. It provides permissionless risk management and permissionless market creation with oracle agnostic pricing. It also enables higher collateralization factors, improved interest rates, and lower gas consumption. The protocol is designed to be a simple, immutable, and governance-minimized base layer that allows for a wide variety of other layers to be built on top. Morpho Blue also offers a convenient developer experience with a singleton implementation, callbacks, free flash loans, and account management features.

Whitepaper

The protocol is described in detail in the Morpho Blue Whitepaper.

Repository Structure

Morpho.sol contains most of the source code of the core contract of Morpho Blue. It solely relies on internal libraries in the src/libraries subdirectory.

Libraries in the src/libraries/periphery directory are not used by Morpho Blue. They are useful helpers that integrators can reuse or adapt to their own needs.

The src/mocks directory contains contracts designed exclusively for testing.

You'll find relevant comments in IMorpho.sol, notably a list of requirements about market dependencies.

Getting Started

Install dependencies: yarn

Run forge tests: yarn test:forge

Run hardhat tests: yarn test:hardhat

You will find other useful commands in the package.json file.

Audits

All audits are stored in the audits' folder.

Licences

The primary license for Morpho Blue is the Business Source License 1.1 (BUSL-1.1), see LICENSE. However, all files in the following folders can also be licensed under GPL-2.0-or-later (as indicated in their SPDX headers): src/interfaces, src/libraries, src/mocks, test, certora.

morpho-blue's People

Contributors

adhusson avatar dependabot[bot] avatar jean-grimal avatar jhoenicke avatar julien-devatom avatar makcandrov avatar mathisgd avatar merlinegalite avatar moodlezoup avatar omahs avatar pakim249cal avatar paulframbot avatar poolpitako avatar qgarchery avatar rubilmax avatar sohkai 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  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  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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

morpho-blue's Issues

Consolidate storage

Separate mappings that make use of the same ID are inefficient, because a new storage hash needs to be calculated for each storage variable accessed. The storage should be consolidated into structs.

Add `README.md`

Things that need to be in it:

  • link to WPP [coming soon]
  • details on licences
  • useful commands and dependencies

Fix roundings

Noted by @pakim249CAL, we don't round correctly (meaning rounding in favor of the protocol) everywhere (borrow/withdraw).

Abstract effects away from checks

If we want a flexible framework for callers to do multiple interactions with blue in one call, then checks like the health factor check should be abstracted to internal functions so that we can make these checks only happen at the end of every call.

Liquidation input and return values

Liquidations are inherently unstable and it may not be possible to predict how much debt a liquidator would repay given an amount of collateral to seize. A return value would allow callers to revert liquidations if the amount of debt to repay is too high for their tolerance.

Repay/Withdraw max

In the past is used to allows a user to pass type(uint256).max and compute the max. On the current code base it's not possible. Should we?

IRM logic improvement proposal

Instead of an IRM accepting a utilization rate and returning a borrow rate, it can accept the total supply, total borrow, and time elapsed, and return a strict amount to accrue rather than a rate.

This is much simpler and easier to understand, and would provide more flexibility since utilization can be derived from the total supply and total borrow trivially.

Blue is vulnerable to price manipulations

The current setup is not suitable for any collateral or debt assets that don't have an extremely reliable oracle. Supplying to the protocol as it stands comes with considerable oracle risk. If we do not implement some safeguards against short term price manipulations, then the only suitable assets will be assets that are already prominent in other lending protocols, putting into question the viability of Blue.

License

Todo:

  • choose the license
  • add it to the repo
  • fill the license field in package.json

Format on commit?

I ran forge fmt in local and it changes the file while I did not change anything. This can be quite annoying when doing changes.

Put "mock" outside of `./src`

"mock" should be in the ./test folder, but hardhat doesn't want to compile source from different files like that.

Share prices can be inflated

Simply setting WAD to be the initial number of shares is vulnerable to the following:

Supply 1.000_000 WBTC for WAD shares.
Withdraw 0.999_999 WBTC for WAD - 1 shares, leaving 1 share left and 0.000_001 WBTC.

Now the intended precision in shares is lost.

Branchless `isHealthy`

isHealthy could be branchless:

could be branchless ๐Ÿค“

    function isHealthy(Market calldata market, Id id, address user) private view returns (bool) {
        uint borrowValue = borrowShare[id][user].wMul(totalBorrow[id]).uwDiv(totalBorrowShares[id]).wMul(market.borrowableOracle.price());
        uint collateralValue = collateral[id][user].wMul(market.collateralOracle.price());
        return collateralValue.wMul(market.lLTV) >= borrowValue;
    }

with

    /// @dev Rounds towards zero.
    function uwDiv(uint x, uint y) internal pure returns (uint z) {
        // This part is "checked".
        z = x * WAD;
        // This part is "unchecked".
        assembly {
            z := div(z, y)
        }
    }

It uses the fact that div(x, 0) outputs 0.

From #4 (comment)

Fix hardhat "uninitialized provider" issue

When using the latest version of hardhat and dependencies, yarn test is failing with this:

Error HH21: You tried to access an uninitialized provider. To initialize the provider, make sure you first call `.init()` or any method that hits a node like request, send or sendAsync.

For more info go to https://hardhat.org/HH21 or run Hardhat with --show-stack-traces
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

It is fixed by using a modified yarn.lock file, but we should find a fix to use the latest version of hardhat.

Working yarn file: yarn.lock.txt
Diff: diff.txt

Liquidators can grief liquidatable positions

By seizing an amount less than the user's total collateral, liquidators can create liquidatable positions that are not worth liquidating. This would result in bad debt not being realized which leaves opportunities for suppliers to withdraw without a bad debt haircut leaving the rest of the suppliers in a bad position.

Should liquidations revert with too high amounts

The liquidate function takes the amount to seize as a parameter. This has been done because:

  • the collateral does not accumulate interests, so the amount to seize is almost synchronous (almost, because there can always be a supply/withdraw collateral before the liquidation)
  • ensures that liquidators can easily take the full collateral, and realize the bad debt. This is important because we want to incentivize the realization of the bad debt.

If we want to take further the idea of making the realization of the bad debt easy, we could try to ensure that liquidations never revert when passing a too high amount. See here for an implementation of this idea.

First step: do not revert when trying to seize more than the collateral of the user

This is an easy step: simply take the min with the collateral of the user. It's also not very useful because the collateral is almost synchronous as stated above, which means that the liquidator could simply pass the collateral amount of the user directly.

Second step: do not revert when trying to repay more than the debt of the user

This step is slightly more complicated: after dividing by the liquidation incentive, we cannot just take the min with the debt of the user, otherwise the liquidators will always take the full collateral, and so it requires to do a little bit more computation.

Pros and cons of those steps

Pros:

  • enforce a standard that incentivizes the realization of the bad debt
  • make it easy for liquidators, they can always pass type(uint).max as the amount seized without reverting. When having stronger assumptions about the liquidators (such that they will deploy their own contract, be almost synchronous, and know the protocol well), this is no longer a real advantage

Cons:

  • slightly more gas, but this is debatable because maybe this computation will have to be done onchain anyway
  • a few more lines of code (4 or 5)
  • can be build on top (but it's less of a standard then)

Consider removing tests

I think it's way too early to have tests. Having to rework tests every time a change is made in early development slows things down unnecessarily.

Should Blue emit event ?

Blue is simple, and recomputing everything one might want off-chain through the function calls only might be doable. Note that TheGraph and Dune index function calls. Thus we can ask ourselves if we really need to emit events. Things at stake include code simplicity, gas cost, and ease of off-chain integration.

This is a big topic, I invoke notably @julien-devatom for this one.

IRMs

Markets should call an arbitrary IRM in a set whitelisted by governance.

Liquidation bonus may not incentivize liquidations appropriately

The liquidation bonus as it currently stands is not flexible enough to accommodate a wide variety of markets. Each market should have its liquidation bonus decided by a market creator, since there are many subjective factors to consider like gas costs, slippage, etc..

Implement `lLTV` tiers

Not all LLTVs can be opened. Similarly to UniV3's fee tiers, the governance lists a set of LLTVs (that can be expended but not reduced).

Unique transfer function

Instead of having safeTransferFrom and safeTransfer, we could have a unique safeTransferFrom that handles the case where the from is address(this) automatically.

Idea of @QGarchery inspired by Mangrove I think.

Oracle could return more things

The onchain team has discussed extensively the utility of having pause flags for things like borrow and liquidation returned by the oracle. This is especially important for less liquid markets to prevent short term price changes from rekting.

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.