Skip to content

Commit

Permalink
Merge branch 'main' of github.com:morpho-labs/blue into feat/repay-wi…
Browse files Browse the repository at this point in the history
…thdraw-all
  • Loading branch information
Rubilmax committed Aug 4, 2023
2 parents 783983a + 8b8a493 commit fd93b63
Show file tree
Hide file tree
Showing 16 changed files with 333 additions and 150 deletions.
159 changes: 100 additions & 59 deletions src/Blue.sol

Large diffs are not rendered by default.

71 changes: 71 additions & 0 deletions src/interfaces/IBlue.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.5.0;

import {IFlashLender} from "./IFlashLender.sol";

type Id is bytes32;

struct Market {
address borrowableAsset;
address collateralAsset;
address borrowableOracle;
address collateralOracle;
address irm;
uint256 lltv;
}

/// @notice Contains the `v`, `r` and `s` parameters of an ECDSA signature.
struct Signature {
uint8 v;
bytes32 r;
bytes32 s;
}

interface IBlue is IFlashLender {
function DOMAIN_SEPARATOR() external view returns (bytes32);

function owner() external view returns (address);
function feeRecipient() external view returns (address);

function supplyShares(Id, address) external view returns (uint256);
function borrowShares(Id, address) external view returns (uint256);
function collateral(Id, address) external view returns (uint256);
function totalSupply(Id) external view returns (uint256);
function totalSupplyShares(Id) external view returns (uint256);
function totalBorrow(Id) external view returns (uint256);
function totalBorrowShares(Id) external view returns (uint256);
function lastUpdate(Id) external view returns (uint256);
function fee(Id) external view returns (uint256);

function isIrmEnabled(address) external view returns (bool);
function isLltvEnabled(uint256) external view returns (bool);
function isAuthorized(address, address) external view returns (bool);
function nonce(address) external view returns (uint256);

function setOwner(address newOwner) external;
function enableIrm(address irm) external;
function enableLltv(uint256 lltv) external;
function setFee(Market memory market, uint256 newFee) external;
function setFeeRecipient(address recipient) external;
function createMarket(Market memory market) external;

function supply(Market memory market, uint256 amount, address onBehalf, bytes memory data) external;
function withdraw(Market memory market, uint256 amount, address onBehalf, address receiver) external;
function borrow(Market memory market, uint256 amount, address onBehalf, address receiver) external;
function repay(Market memory market, uint256 amount, address onBehalf, bytes memory data) external;
function supplyCollateral(Market memory market, uint256 amount, address onBehalf, bytes memory data) external;
function withdrawCollateral(Market memory market, uint256 amount, address onBehalf, address receiver) external;
function liquidate(Market memory market, address borrower, uint256 seized, bytes memory data) external;
function flashLoan(address token, uint256 amount, bytes calldata data) external;

function setAuthorization(address manager, bool isAllowed) external;
function setAuthorization(
address authorizer,
address authorized,
bool newIsAuthorized,
uint256 deadline,
Signature calldata signature
) external;

function extsload(bytes32[] memory slots) external view returns (bytes32[] memory res);
}
4 changes: 4 additions & 0 deletions src/interfaces/IBlueCallbacks.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,7 @@ interface IBlueSupplyCallback {
interface IBlueSupplyCollateralCallback {
function onBlueSupplyCollateral(uint256 amount, bytes calldata data) external;
}

interface IBlueFlashLoanCallback {
function onBlueFlashLoan(address token, uint256 amount, bytes calldata data) external;
}
11 changes: 0 additions & 11 deletions src/interfaces/IFlashBorrower.sol

This file was deleted.

9 changes: 2 additions & 7 deletions src/interfaces/IFlashLender.sol
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.5.0;

import {IFlashBorrower} from "src/interfaces/IFlashBorrower.sol";
import {IBlueFlashLoanCallback} from "./IBlueCallbacks.sol";

interface IFlashLender {
/// @dev Initiate a flash loan.
/// @param receiver The receiver of the tokens in the loan, and the receiver of the callback.
/// @param token The token lent.
/// @param amount The amount of tokens lent.
/// @param data Arbitrary data structure, intended to contain user-defined parameters.
function flashLoan(IFlashBorrower receiver, address token, uint256 amount, bytes calldata data) external;
function flashLoan(address token, uint256 amount, bytes calldata data) external;
}
2 changes: 1 addition & 1 deletion src/interfaces/IIrm.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.5.0;

import {Market} from "src/libraries/MarketLib.sol";
import {Market} from "./IBlue.sol";

interface IIrm {
function borrowRate(Market memory market) external returns (uint256);
Expand Down
2 changes: 2 additions & 0 deletions src/libraries/Errors.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ library Errors {

string internal constant ZERO_AMOUNT = "zero amount";

string internal constant ZERO_ADDRESS = "zero address";

string internal constant UNAUTHORIZED = "unauthorized";

string internal constant INSUFFICIENT_COLLATERAL = "insufficient collateral";
Expand Down
63 changes: 63 additions & 0 deletions src/libraries/Events.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import {Id, Market} from "src/libraries/MarketLib.sol";

library Events {
event SupplyCollateral(Id indexed id, address indexed caller, address indexed onBehalf, uint256 amount);
event WithdrawCollateral(
Id indexed id, address caller, address indexed onBehalf, address indexed receiver, uint256 amount
);

event Supply(Id indexed id, address indexed caller, address indexed onBehalf, uint256 amount, uint256 shares);
event Withdraw(
Id indexed id,
address caller,
address indexed onBehalf,
address indexed receiver,
uint256 amount,
uint256 shares
);

event Borrow(
Id indexed id,
address caller,
address indexed onBehalf,
address indexed receiver,
uint256 amount,
uint256 shares
);
event Repay(Id indexed id, address indexed caller, address indexed onBehalf, uint256 amount, uint256 shares);

event Liquidate(
Id indexed id,
address indexed caller,
address indexed borrower,
uint256 repaid,
uint256 repaidShares,
uint256 seized,
uint256 badDebtShares
);

event FlashLoan(address indexed caller, address indexed token, uint256 amount);

event SetOwner(address indexed newOwner);

event SetFee(Id indexed id, uint256 fee);

event SetFeeRecipient(address indexed feeRecipient);

event CreateMarket(Id indexed id, Market market);

event SetAuthorization(
address indexed caller, address indexed authorizer, address indexed authorized, bool isAuthorized
);

event IncrementNonce(address indexed caller, address indexed signatory, uint256 usedNonce);

event EnableIrm(address indexed irm);

event EnableLltv(uint256 lltv);

event AccrueInterests(Id indexed id, uint256 borrowRate, uint256 accruedInterests, uint256 feeShares);
}
15 changes: 1 addition & 14 deletions src/libraries/MarketLib.sol
Original file line number Diff line number Diff line change
@@ -1,20 +1,7 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import {IIrm} from "src/interfaces/IIrm.sol";
import {IERC20} from "src/interfaces/IERC20.sol";
import {IOracle} from "src/interfaces/IOracle.sol";

type Id is bytes32;

struct Market {
IERC20 borrowableAsset;
IERC20 collateralAsset;
IOracle borrowableOracle;
IOracle collateralOracle;
IIrm irm;
uint256 lltv;
}
import {Id, Market, IBlue} from "../interfaces/IBlue.sol";

library MarketLib {
function id(Market memory market) internal pure returns (Id) {
Expand Down
2 changes: 1 addition & 1 deletion src/libraries/SafeTransferLib.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import {IERC20} from "src/interfaces/IERC20.sol";
import {IERC20} from "../interfaces/IERC20.sol";

/// @notice Safe ERC20 transfer library that gracefully handles missing return values.
/// @dev Greatly inspired by Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol).
Expand Down
2 changes: 1 addition & 1 deletion src/mocks/ERC20Mock.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.21;
pragma solidity ^0.8.0;

import {ERC20} from "solmate/tokens/ERC20.sol";

Expand Down
24 changes: 12 additions & 12 deletions src/mocks/FlashBorrowerMock.sol
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import {IFlashLender} from "src/interfaces/IFlashLender.sol";
import {IFlashBorrower} from "src/interfaces/IFlashBorrower.sol";
import {IFlashLender} from "../interfaces/IFlashLender.sol";
import {IBlueFlashLoanCallback} from "../interfaces/IBlueCallbacks.sol";

import {ERC20, SafeTransferLib} from "solmate/utils/SafeTransferLib.sol";

contract FlashBorrowerMock is IFlashBorrower {
contract FlashBorrowerMock is IBlueFlashLoanCallback {
using SafeTransferLib for ERC20;

IFlashLender private immutable _LENDER;
IFlashLender private immutable BLUE;

constructor(IFlashLender lender) {
_LENDER = lender;
constructor(IFlashLender newBlue) {
BLUE = newBlue;
}

/* EXTERNAL */

/// @inheritdoc IFlashBorrower
function onBlueFlashLoan(address, address token, uint256 amount, bytes calldata) external {
require(msg.sender == address(_LENDER), "invalid lender");
function flashLoan(address token, uint256 amount, bytes calldata data) external {
BLUE.flashLoan(token, amount, data);
}

ERC20(token).safeApprove(address(_LENDER), amount);
function onBlueFlashLoan(address token, uint256 amount, bytes calldata) external {
require(msg.sender == address(BLUE));
ERC20(token).safeApprove(address(BLUE), amount);
}
}
19 changes: 9 additions & 10 deletions src/mocks/IrmMock.sol
Original file line number Diff line number Diff line change
@@ -1,26 +1,25 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.21;
pragma solidity ^0.8.0;

import {IIrm} from "src/interfaces/IIrm.sol";
import {IIrm} from "../interfaces/IIrm.sol";
import {Id, Market, IBlue} from "../interfaces/IBlue.sol";

import {FixedPointMathLib} from "src/libraries/FixedPointMathLib.sol";
import {Id, Market, MarketLib} from "src/libraries/MarketLib.sol";

import {Blue} from "src/Blue.sol";
import {FixedPointMathLib} from "../libraries/FixedPointMathLib.sol";
import {MarketLib} from "../libraries/MarketLib.sol";

contract IrmMock is IIrm {
using FixedPointMathLib for uint256;
using MarketLib for Market;

Blue public immutable blue;
IBlue private immutable BLUE;

constructor(Blue blueInstance) {
blue = Blue(blueInstance);
constructor(IBlue blue) {
BLUE = blue;
}

function borrowRate(Market memory market) external view returns (uint256) {
Id id = market.id();
uint256 utilization = blue.totalBorrow(id).divWadDown(blue.totalSupply(id));
uint256 utilization = BLUE.totalBorrow(id).divWadDown(BLUE.totalSupply(id));

// Divide by the number of seconds in a year.
// This is a very simple model (to refine later) where x% utilization corresponds to x% APR.
Expand Down
4 changes: 2 additions & 2 deletions src/mocks/OracleMock.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.21;
pragma solidity ^0.8.0;

import {IOracle} from "src/interfaces/IOracle.sol";
import {IOracle} from "../interfaces/IOracle.sol";

contract OracleMock is IOracle {
uint256 public price;
Expand Down
Loading

0 comments on commit fd93b63

Please sign in to comment.