Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor testing suite #218

Merged
merged 72 commits into from
Aug 15, 2023
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
72 commits
Select commit Hold shift + click to select a range
d073155
refactor: delete tests
makcandrov Aug 3, 2023
e8caf81
Revert "refactor: delete tests"
makcandrov Aug 3, 2023
ca0dbe2
fix: remove flashloan receiver
makcandrov Aug 3, 2023
c509d12
feat: add set authorization tests
Jean-Grimal Aug 3, 2023
60993fd
refactor: delete old tests
makcandrov Aug 3, 2023
47e7eb3
Merge branch 'feat/tests' of github.com:morpho-labs/blue into feat/tests
makcandrov Aug 3, 2023
6f2d1b4
Merge branch 'test/tree' into feat/tests
makcandrov Aug 3, 2023
4ce8f65
feat: add accrued interests integration tests
Jean-Grimal Aug 3, 2023
26a34c9
test: improve test borrow
makcandrov Aug 3, 2023
067a888
Merge branch 'test/tree' into feat/tests
makcandrov Aug 3, 2023
cb6e845
refactor: borrow and withdraw collateral tests
makcandrov Aug 4, 2023
2b17afa
refactor: withdraw tests
makcandrov Aug 4, 2023
baaeff8
refactor: testLiquidateHealthyPosition
makcandrov Aug 4, 2023
e29da38
style: format
makcandrov Aug 4, 2023
05e8d38
refactor: testLiquidateNoBadDebt
makcandrov Aug 4, 2023
0d5733d
refactor: testLiquidateBadDebt
makcandrov Aug 4, 2023
3e7bd88
style: formatting
makcandrov Aug 4, 2023
68515b1
Merge branch 'test/tree' into feat/tests
makcandrov Aug 4, 2023
0ba62c5
feat: add getter and callbacks integration tests
Jean-Grimal Aug 4, 2023
5549bac
feat: first events
makcandrov Aug 7, 2023
89deed3
feat: events
makcandrov Aug 7, 2023
a2b61c4
feat: test liquidate events
makcandrov Aug 7, 2023
72a73b2
Apply suggestions from code review
makcandrov Aug 8, 2023
8758178
style: harmonize comments and typo
makcandrov Aug 8, 2023
af92791
fix: clean BlueBase.t.sol
Jean-Grimal Aug 8, 2023
b23d478
refactor: more fuzz in borrow tests
makcandrov Aug 8, 2023
3cfaa2c
Merge branch 'feat/tests' of github.com:morpho-labs/blue into feat/tests
makcandrov Aug 8, 2023
ae363b6
fix: remove useless line
makcandrov Aug 8, 2023
6918dd9
fix: constant max test amount
Jean-Grimal Aug 8, 2023
5cf6f8f
refactor: create market tests
makcandrov Aug 8, 2023
3fc6e27
fix: fix conflicts
Jean-Grimal Aug 8, 2023
9fc4b95
feat: more fuzzing in test withdraw collateral
makcandrov Aug 8, 2023
e3a122a
Merge remote-tracking branch 'origin/feat/tests' into feat/tests
makcandrov Aug 8, 2023
dc3dba2
fix: exact borrow shares
makcandrov Aug 8, 2023
7b60fcc
fix: test total shares
makcandrov Aug 8, 2023
64cf487
feat: merge supply on behalf tests
makcandrov Aug 8, 2023
0eab3da
feat: more fuzzing in supply tests
makcandrov Aug 8, 2023
244c652
feat: labelled addresses
makcandrov Aug 8, 2023
a178fee
fix: apply suggestions
makcandrov Aug 8, 2023
f90fba7
style: rename files
makcandrov Aug 8, 2023
b8d11a7
style: use market lib to compute the id
makcandrov Aug 8, 2023
4698b51
fix: remove useless vm.assume
makcandrov Aug 8, 2023
1b29907
fix: rename unknown market to market not created
makcandrov Aug 8, 2023
a18d925
style: use the SECP256K1_ORDER constant
makcandrov Aug 9, 2023
e2b62fd
feat: invalid nonce and signature replay tests
makcandrov Aug 9, 2023
c50d042
style: string to address internal function
makcandrov Aug 9, 2023
edbba16
Merge branch 'test/tree' into feat/tests
makcandrov Aug 10, 2023
304cdb7
fix: comment and wad
makcandrov Aug 10, 2023
63f7a9f
style: format
makcandrov Aug 10, 2023
b35c265
feat: add supply and withdraw shares tests
Jean-Grimal Aug 10, 2023
4de662c
feat: warp in the set up
makcandrov Aug 11, 2023
3e4ca66
Merge branch 'main' into feat/tests
makcandrov Aug 11, 2023
5926858
fix: merge
makcandrov Aug 11, 2023
927d896
feat: add borrow and repay shares tests
Jean-Grimal Aug 11, 2023
e537bdf
Merge branch 'feat/tests' of github.com:morpho-labs/morpho-blue into …
Jean-Grimal Aug 11, 2023
781f80d
Delete Blue.t.sol
Jean-Grimal Aug 11, 2023
16f8cee
refactor: morpho naming
Jean-Grimal Aug 11, 2023
ae9962f
fix: tests after merges
Jean-Grimal Aug 14, 2023
150f5a7
fix: liquidate callback test
Jean-Grimal Aug 14, 2023
3b36a3a
fix: signatures nonce verification
Jean-Grimal Aug 14, 2023
18bed11
feat: add return value tests
Jean-Grimal Aug 14, 2023
6077851
fix: formatting.yml
Jean-Grimal Aug 14, 2023
847fa82
fix: forge fmt
Jean-Grimal Aug 14, 2023
6841e59
fix: accrue interests with accrueInterests function
Jean-Grimal Aug 14, 2023
be37f98
refactor: rename borrowableAsset to borrowableToken (same for collate…
Jean-Grimal Aug 14, 2023
4478931
feat: add liquidate return value test
Jean-Grimal Aug 14, 2023
72cd0d5
fix: forge fmt
Jean-Grimal Aug 14, 2023
53228b9
fix: accrue interests shares fee computation
Jean-Grimal Aug 15, 2023
a503e51
fix: no fuzz on addresses, and increase max amounts
Jean-Grimal Aug 15, 2023
85fc322
fix: forge fmt
Jean-Grimal Aug 15, 2023
4aa66f5
docs: apply suggestions
MerlinEgalite Aug 15, 2023
32c15cd
refactor: lint
MerlinEgalite Aug 15, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[submodule "lib/forge-std"]
path = lib/forge-std
url = https://github.com/foundry-rs/forge-std
[submodule "lib/solmate"]
path = lib/solmate
url = https://github.com/transmissions11/solmate
[submodule "lib/openzeppelin-contracts"]
path = lib/openzeppelin-contracts
url = https://github.com/OpenZeppelin/openzeppelin-contracts
1 change: 1 addition & 0 deletions lib/openzeppelin-contracts
Submodule openzeppelin-contracts added at fd81a9
1 change: 0 additions & 1 deletion lib/solmate
Submodule solmate deleted from bfc9c2
2 changes: 1 addition & 1 deletion remappings.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
ds-test/=lib/forge-std/lib/ds-test/src/
forge-std/=lib/forge-std/src/
solmate/=lib/solmate/src/
openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/
290 changes: 176 additions & 114 deletions src/Blue.sol → src/Morpho.sol

Large diffs are not rendered by default.

74 changes: 0 additions & 74 deletions src/interfaces/IBlue.sol

This file was deleted.

22 changes: 0 additions & 22 deletions src/interfaces/IBlueCallbacks.sol

This file was deleted.

10 changes: 7 additions & 3 deletions src/interfaces/IERC20.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.5.0;

/// @dev Empty because we only call functions in assembly. It prevents calling
/// transfer (transferFrom) instead of safeTransfer (safeTransferFrom).
interface IERC20 {}
/// @title IERC20
/// @author Morpho Labs
/// @custom:contact [email protected]
interface IERC20 {
function transfer(address to, uint256 value) external returns (bool);
function transferFrom(address from, address to, uint256 value) external returns (bool);
}
12 changes: 9 additions & 3 deletions src/interfaces/IFlashLender.sol
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.5.0;

import {IBlueFlashLoanCallback} from "./IBlueCallbacks.sol";

/// @title IFlashLender
/// @author Morpho Labs
/// @custom:contact [email protected]
/// @notice Flash lender interface exposing a flash loan function.
interface IFlashLender {
function flashLoan(address token, uint256 amount, bytes calldata data) external;
/// @notice Executes a flash loan.
/// @param token The token to flash loan.
/// @param assets The amount of assets to flash loan.
/// @param data Arbitrary data to pass to the `onMorphoFlashLoan` callback.
function flashLoan(address token, uint256 assets, bytes calldata data) external;
}
7 changes: 6 additions & 1 deletion src/interfaces/IIrm.sol
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.5.0;

import {Market} from "./IBlue.sol";
import {Market} from "./IMorpho.sol";

/// @title IIrm
/// @author Morpho Labs
/// @custom:contact [email protected]
/// @notice Interface that IRMs used by Morpho must implement.
interface IIrm {
/// @notice Returns the borrow rate of a `market`.
function borrowRate(Market memory market) external returns (uint256);
}
233 changes: 233 additions & 0 deletions src/interfaces/IMorpho.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.5.0;

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

type Id is bytes32;

/// @notice Contains the parameters defining market.
/// @param borrowableToken The address of the borrowable token.
/// @param collateralToken The address of the collateral token.
/// @param oracle The address of the oracle.
/// @param irm The address of the interest rate model.
/// @param lltv The Liquidation LTV.
struct Market {
address borrowableToken;
address collateralToken;
address oracle;
address irm;
uint256 lltv;
}

/// @notice Authorization struct.
/// @param authorizer Authorizer address.
/// @param authorized Authorized address.
/// @param isAuthorized The authorization status to set.
/// @param nonce Signature nonce.
/// @param deadline Signature deadline.
struct Authorization {
address authorizer;
address authorized;
bool isAuthorized;
uint256 nonce;
uint256 deadline;
}

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

/// @title IMorpho
/// @author Morpho Labs
/// @custom:contact [email protected]
/// @notice Interface of Morpho.
interface IMorpho is IFlashLender {
/// @notice The EIP-712 domain separator.
function DOMAIN_SEPARATOR() external view returns (bytes32);

/// @notice The owner of the contract.
function owner() external view returns (address);

/// @notice The fee recipient.
/// @dev The recipient receives the fees through a supply position.
function feeRecipient() external view returns (address);

/// @notice The `user`'s supply shares on the market `id`.
function supplyShares(Id id, address user) external view returns (uint256);

/// @notice The `user`'s borrow shares on the market `id`.
function borrowShares(Id, address user) external view returns (uint256);

/// @notice The `user`'s collateral balance on the market `id`.
function collateral(Id id, address user) external view returns (uint256);

/// @notice The total supply of the market `id`.
/// @dev Does not contain the accrued interest since the last interaction.
function totalSupply(Id id) external view returns (uint256);

/// @notice The total supply shares of the market `id`.
function totalSupplyShares(Id id) external view returns (uint256);

/// @notice The total borrow of the market `id`.
/// @dev Does not contain the accrued interest since the last interaction.
function totalBorrow(Id id) external view returns (uint256);

/// @notice The total borrow shares of the market `id`.
function totalBorrowShares(Id id) external view returns (uint256);

/// @notice The last update timestamp of the market `id` (also used to check if a market has been created).
function lastUpdate(Id id) external view returns (uint256);

/// @notice The fee of the market `id`.
function fee(Id id) external view returns (uint256);

/// @notice Whether the `irm` is enabled.
function isIrmEnabled(address irm) external view returns (bool);

/// @notice Whether the `lltv` is enabled.
function isLltvEnabled(uint256 lltv) external view returns (bool);

/// @notice Whether `authorized` is authorized to modify `authorizer`'s positions.
/// @dev Anyone is authorized to modify their own positions, regardless of this variable.
function isAuthorized(address authorizer, address authorized) external view returns (bool);

/// @notice The `user`'s current nonce. Used to prevent replay attacks with EIP-712 signatures.
function nonce(address user) external view returns (uint256);

/// @notice Sets `newOwner` as owner of the contract.
function setOwner(address newOwner) external;

/// @notice Enables `irm` as possible IRM for market creation.
function enableIrm(address irm) external;

/// @notice Enables `lltv` as possible LLTV for market creation.
function enableLltv(uint256 lltv) external;

/// @notice Sets the `newFee` for `market`.
/// @dev It is the `owner`'s responsibility to ensure `feeRecipient` is set before setting a non-zero fee.
function setFee(Market memory market, uint256 newFee) external;

/// @notice Sets `recipient` as recipient of the fee.
function setFeeRecipient(address recipient) external;

/// @notice Creates `market`.
function createMarket(Market memory market) external;

/// @notice Supplies the given `assets` or `shares` to the given `market` on behalf of `onBehalf`,
/// optionally calling back the caller's `onMorphoSupply` function with the given `data`.
/// @dev Either `assets` or `shares` should be zero.
/// Most usecases should rely on `assets` as an input so the caller
/// is guaranteed to have `assets` tokens pulled from their balance,
/// but the possibility to mint a specific assets of shares is given
/// for full compatibility and precision.
/// @dev Supplying a large amount can overflow and revert without any error message.
/// @param market The market to supply assets to.
/// @param assets The assets of assets to supply.
/// @param shares The assets of shares to mint.
/// @param onBehalf The address that will receive the position.
/// @param data Arbitrary data to pass to the `onMorphoSupply` callback. Pass empty data if not needed.
/// @return assetsSupplied The assets of assets supplied.
/// @return sharesSupplied The assets of shares supplied.
function supply(Market memory market, uint256 assets, uint256 shares, address onBehalf, bytes memory data)
external
returns (uint256 assetsSupplied, uint256 sharesSupplied);

/// @notice Withdraws the given `assets` or `shares` from the given `market` on behalf of `onBehalf`.
/// @dev Either `assets` or `shares` should be zero.
/// To withdraw the whole position, pass the `shares`'s balance of `onBehalf`.
/// @dev `msg.sender` must be authorized to manage `onBehalf`'s positions.
/// @dev Withdrawing an amount corresponding to more shares than supplied will underflow and revert without any error message.
/// @param market The market to withdraw assets from.
/// @param shares The assets of assets to withdraw.
/// @param shares The assets of shares to burn.
/// @param onBehalf The address of the owner of the withdrawn assets.
/// @param receiver The address that will receive the withdrawn assets.
/// @return assetsWithdrawn The assets of assets withdrawn.
/// @return sharesWithdrawn The assets of shares withdrawn.
function withdraw(Market memory market, uint256 assets, uint256 shares, address onBehalf, address receiver)
external
returns (uint256 assetsWithdrawn, uint256 sharesWithdrawn);

/// @notice Borrows the given `assets` or `shares` from the given `market` on behalf of `onBehalf`.
/// @dev Either `assets` or `shares` should be zero.
/// Most usecases should rely on `assets` as an input so the caller
/// is guaranteed to borrow `assets` of tokens,
/// but the possibility to burn a specific assets of shares is given
/// for full compatibility and precision.
/// @dev `msg.sender` must be authorized to manage `onBehalf`'s positions.
/// @dev Borrowing a large amount can overflow and revert without any error message.
/// @param market The market to borrow assets from.
/// @param assets The assets of assets to borrow.
/// @param shares The assets of shares to mint.
/// @param onBehalf The address of the owner of the debt.
/// @param receiver The address that will receive the debt.
/// @return assetsBorrowed The assets of assets borrowed.
/// @return sharesBorrowed The assets of shares borrowed.
function borrow(Market memory market, uint256 assets, uint256 shares, address onBehalf, address receiver)
external
returns (uint256 assetsBorrowed, uint256 sharesBorrowed);

/// @notice Repays the given `assets` or `shares` to the given `market` on behalf of `onBehalf`,
/// optionally calling back the caller's `onMorphoReplay` function with the given `data`.
/// @dev Either `assets` or `shares` should be zero.
/// To repay the whole debt, pass the `shares`'s balance of `onBehalf`.
/// @dev Repaying an amount corresponding to more shares than borrowed will underflow and revert without any error message.
/// @param market The market to repay assets to.
/// @param assets The assets of assets to repay.
/// @param shares The assets of shares to burn.
/// @param onBehalf The address of the owner of the debt.
/// @param data Arbitrary data to pass to the `onMorphoRepay` callback. Pass empty data if not needed.
/// @return assetsRepaid The assets of assets repaid.
/// @return sharesRepaid The assets of shares repaid.
function repay(Market memory market, uint256 assets, uint256 shares, address onBehalf, bytes memory data)
external
returns (uint256 assetsRepaid, uint256 sharesRepaid);

/// @notice Supplies the given `assets` of collateral to the given `market` on behalf of `onBehalf`,
/// optionally calling back the caller's `onMorphoSupplyCollateral` function with the given `data`.
/// @dev Interests are not accrued since it's not required and it saves gas.
/// @dev Supplying a large amount can overflow and revert without any error message.
/// @param market The market to supply collateral to.
/// @param assets The assets of collateral to supply.
/// @param onBehalf The address that will receive the collateral.
/// @param data Arbitrary data to pass to the `onMorphoSupplyCollateral` callback. Pass empty data if not needed.
function supplyCollateral(Market memory market, uint256 assets, address onBehalf, bytes memory data) external;

/// @notice Withdraws the given `assets` of collateral from the given `market` on behalf of `onBehalf`.
/// @dev `msg.sender` must be authorized to manage `onBehalf`'s positions.
/// @dev Withdrawing an amount corresponding to more collateral than supplied will underflow and revert without any error message.
/// @param market The market to withdraw collateral from.
/// @param assets The assets of collateral to withdraw.
/// @param onBehalf The address of the owner of the collateral.
/// @param receiver The address that will receive the withdrawn collateral.
function withdrawCollateral(Market memory market, uint256 assets, address onBehalf, address receiver) external;

/// @notice Liquidates the given `seized` assets to the given `market` of the given `borrower`'s position,
/// optionally calling back the caller's `onMorphoLiquidate` function with the given `data`.
/// @dev Seizing more than the collateral balance will underflow and revert without any error message.
/// @dev Repaying more than the borrow balance will underflow and revert without any error message.
/// @param market The market of the position.
/// @param borrower The owner of the position.
/// @param seized The assets of collateral to seize.
/// @param data Arbitrary data to pass to the `onMorphoLiquidate` callback. Pass empty data if not needed
function liquidate(Market memory market, address borrower, uint256 seized, bytes memory data) external;

/// @notice Sets the authorization for `authorized` to manage `msg.sender`'s positions.
/// @param authorized The authorized address.
/// @param newIsAuthorized The new authorization status.
function setAuthorization(address authorized, bool newIsAuthorized) external;

/// @notice Sets the authorization for `authorization.authorized` to manage `authorization.authorizer`'s positions.
/// @param authorization The `Authorization` struct.
/// @param signature The signature.
function setAuthorizationWithSig(Authorization calldata authorization, Signature calldata signature) external;

/// @notice Accrues interests for `market`.
function accrueInterests(Market memory market) external;

/// @notice Returns the data stored on the different `slots`.
function extsload(bytes32[] memory slots) external view returns (bytes32[] memory res);
}
Loading