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

MorphoLib perf and test #384

Merged
merged 4 commits into from
Aug 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
54 changes: 35 additions & 19 deletions src/libraries/periphery/MorphoLib.sol
Original file line number Diff line number Diff line change
@@ -1,42 +1,58 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import {IMorpho, Id} from "../../Morpho.sol";
import {IMorpho, Id} from "../../interfaces/IMorpho.sol";
import {MorphoStorageLib} from "./MorphoStorageLib.sol";

library MorphoLib {
function supplyShares(IMorpho morpho, Id id, address user) internal view returns (uint256 res) {
(res,,) = morpho.user(id, user);
function supplyShares(IMorpho morpho, Id id, address user) internal view returns (uint256) {
bytes32[] memory slot = _array(MorphoStorageLib.userSupplySharesSlot(id, user));
return uint256(morpho.extSloads(slot)[0]);
}

function borrowShares(IMorpho morpho, Id id, address user) internal view returns (uint256 res) {
(, res,) = morpho.user(id, user);
function borrowShares(IMorpho morpho, Id id, address user) internal view returns (uint256) {
bytes32[] memory slot = _array(MorphoStorageLib.userBorrowSharesAndCollateralSlot(id, user));
return uint128(uint256(morpho.extSloads(slot)[0]));
}

function collateral(IMorpho morpho, Id id, address user) internal view returns (uint256 res) {
(,, res) = morpho.user(id, user);
function collateral(IMorpho morpho, Id id, address user) internal view returns (uint256) {
bytes32[] memory slot = _array(MorphoStorageLib.userBorrowSharesAndCollateralSlot(id, user));
return uint256(morpho.extSloads(slot)[0] >> 128);
}

function totalSupplyAssets(IMorpho morpho, Id id) internal view returns (uint256 res) {
(res,,,,,) = morpho.market(id);
function totalSupplyAssets(IMorpho morpho, Id id) internal view returns (uint256) {
bytes32[] memory slot = _array(MorphoStorageLib.marketTotalSupplyAssetsAndSharesSlot(id));
return uint128(uint256(morpho.extSloads(slot)[0]));
}

function totalSupplyShares(IMorpho morpho, Id id) internal view returns (uint256 res) {
(, res,,,,) = morpho.market(id);
function totalSupplyShares(IMorpho morpho, Id id) internal view returns (uint256) {
bytes32[] memory slot = _array(MorphoStorageLib.marketTotalSupplyAssetsAndSharesSlot(id));
return uint256(morpho.extSloads(slot)[0] >> 128);
}

function totalBorrowAssets(IMorpho morpho, Id id) internal view returns (uint256 res) {
(,, res,,,) = morpho.market(id);
function totalBorrowAssets(IMorpho morpho, Id id) internal view returns (uint256) {
bytes32[] memory slot = _array(MorphoStorageLib.marketTotalBorrowAssetsAndSharesSlot(id));
return uint128(uint256(morpho.extSloads(slot)[0]));
}

function totalBorrowShares(IMorpho morpho, Id id) internal view returns (uint256 res) {
(,,, res,,) = morpho.market(id);
function totalBorrowShares(IMorpho morpho, Id id) internal view returns (uint256) {
bytes32[] memory slot = _array(MorphoStorageLib.marketTotalBorrowAssetsAndSharesSlot(id));
return uint256(morpho.extSloads(slot)[0] >> 128);
}

function lastUpdate(IMorpho morpho, Id id) internal view returns (uint256 res) {
(,,,, res,) = morpho.market(id);
function lastUpdate(IMorpho morpho, Id id) internal view returns (uint256) {
bytes32[] memory slot = _array(MorphoStorageLib.marketLastUpdateAndFeeSlot(id));
return uint128(uint256(morpho.extSloads(slot)[0]));
}

function fee(IMorpho morpho, Id id) internal view returns (uint256 res) {
(,,,,, res) = morpho.market(id);
function fee(IMorpho morpho, Id id) internal view returns (uint256) {
bytes32[] memory slot = _array(MorphoStorageLib.marketLastUpdateAndFeeSlot(id));
return uint256(morpho.extSloads(slot)[0] >> 128);
}

function _array(bytes32 x) private pure returns (bytes32[] memory) {
bytes32[] memory res = new bytes32[](1);
res[0] = x;
return res;
MathisGD marked this conversation as resolved.
Show resolved Hide resolved
}
}
113 changes: 113 additions & 0 deletions test/forge/periphery/MorphoLib.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import {MorphoBalancesLib} from "src/libraries/periphery/MorphoBalancesLib.sol";

import "../BaseTest.sol";

contract MorphoLibTest is BaseTest {
using MathLib for uint256;
using MorphoLib for Morpho;

function _testMorphoLibCommon(uint256 amountSupplied, uint256 amountBorrowed, uint256 timestamp, uint256 fee)
MathisGD marked this conversation as resolved.
Show resolved Hide resolved
private
{
// Prepare storage layout with non empty values.

amountSupplied = bound(amountSupplied, 2, MAX_TEST_AMOUNT);
amountBorrowed = bound(amountBorrowed, 1, amountSupplied);
timestamp = bound(timestamp, block.timestamp, type(uint32).max);
fee = bound(fee, 0, MAX_FEE);

// Set fee parameters.
vm.prank(OWNER);
morpho.setFee(market, fee);

// Set timestamp.
vm.warp(timestamp);

borrowableToken.setBalance(address(this), amountSupplied);
morpho.supply(market, amountSupplied, 0, address(this), hex"");

uint256 collateralPrice = IOracle(market.oracle).price();
collateralToken.setBalance(BORROWER, amountBorrowed.wDivUp(LLTV).mulDivUp(ORACLE_PRICE_SCALE, collateralPrice));

vm.startPrank(BORROWER);
morpho.supplyCollateral(
market, amountBorrowed.wDivUp(LLTV).mulDivUp(ORACLE_PRICE_SCALE, collateralPrice), BORROWER, hex""
);
morpho.borrow(market, amountBorrowed, 0, BORROWER, BORROWER);
vm.stopPrank();
}

function testSupplyShares(uint256 amountSupplied, uint256 amountBorrowed, uint256 timestamp, uint256 fee) public {
_testMorphoLibCommon(amountSupplied, amountBorrowed, timestamp, fee);

(uint256 expectedSupplyShares,,) = morpho.user(id, address(this));
assertEq(morpho.supplyShares(id, address(this)), expectedSupplyShares);
}

function testBorrowShares(uint256 amountSupplied, uint256 amountBorrowed, uint256 timestamp, uint256 fee) public {
_testMorphoLibCommon(amountSupplied, amountBorrowed, timestamp, fee);

(, uint256 expectedBorrowShares,) = morpho.user(id, BORROWER);
assertEq(morpho.borrowShares(id, BORROWER), expectedBorrowShares);
}

function testCollateral(uint256 amountSupplied, uint256 amountBorrowed, uint256 timestamp, uint256 fee) public {
_testMorphoLibCommon(amountSupplied, amountBorrowed, timestamp, fee);

(,, uint256 expectedCollateral) = morpho.user(id, BORROWER);
assertEq(morpho.collateral(id, BORROWER), expectedCollateral);
}

function testTotalSupplyAssets(uint256 amountSupplied, uint256 amountBorrowed, uint256 timestamp, uint256 fee)
public
{
_testMorphoLibCommon(amountSupplied, amountBorrowed, timestamp, fee);

(uint256 expectedTotalSupplyAssets,,,,,) = morpho.market(id);
assertEq(morpho.totalSupplyAssets(id), expectedTotalSupplyAssets);
}

function testTotalSupplyShares(uint256 amountSupplied, uint256 amountBorrowed, uint256 timestamp, uint256 fee)
public
{
_testMorphoLibCommon(amountSupplied, amountBorrowed, timestamp, fee);

(, uint256 expectedTotalSupplyShares,,,,) = morpho.market(id);
assertEq(morpho.totalSupplyShares(id), expectedTotalSupplyShares);
}

function testTotalBorrowAssets(uint256 amountSupplied, uint256 amountBorrowed, uint256 timestamp, uint256 fee)
public
{
_testMorphoLibCommon(amountSupplied, amountBorrowed, timestamp, fee);

(,, uint256 expectedTotalBorrowAssets,,,) = morpho.market(id);
assertEq(morpho.totalBorrowAssets(id), expectedTotalBorrowAssets);
}

function testTotalBorrowShares(uint256 amountSupplied, uint256 amountBorrowed, uint256 timestamp, uint256 fee)
public
{
_testMorphoLibCommon(amountSupplied, amountBorrowed, timestamp, fee);

(,,, uint256 expectedTotalBorrowShares,,) = morpho.market(id);
assertEq(morpho.totalBorrowShares(id), expectedTotalBorrowShares);
}

function testLastUpdate(uint256 amountSupplied, uint256 amountBorrowed, uint256 timestamp, uint256 fee) public {
_testMorphoLibCommon(amountSupplied, amountBorrowed, timestamp, fee);

(,,,, uint256 expectedLastUpdate,) = morpho.market(id);
assertEq(morpho.lastUpdate(id), expectedLastUpdate);
}

function testFee(uint256 amountSupplied, uint256 amountBorrowed, uint256 timestamp, uint256 fee) public {
_testMorphoLibCommon(amountSupplied, amountBorrowed, timestamp, fee);

(,,,,, uint256 expectedFee) = morpho.market(id);
assertEq(morpho.fee(id), expectedFee);
}
}