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

feat(accrued-interests): add interests library #171

Merged
merged 34 commits into from
Aug 17, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
b7fc2b1
feat(accrued-interests): add interests library
Rubilmax Jul 25, 2023
569fb46
Merge branch 'main' of github.com:morpho-labs/blue into feat/accrued-…
Rubilmax Aug 7, 2023
8198775
refactor(accrued-interests): remove overwhelming return variables
Rubilmax Aug 7, 2023
5378fc0
fix(storage-slots): fix bad slots
Rubilmax Aug 7, 2023
f35b640
Merge branch 'feat/public-accrue-interests' of github.com:morpho-labs…
Rubilmax Aug 11, 2023
84022c7
Merge branch 'main' of github.com:morpho-labs/morpho-blue into feat/a…
MerlinEgalite Aug 15, 2023
61ead50
refactor: rename blue -> morpho
MerlinEgalite Aug 15, 2023
61563cc
feat: add updated getters
MerlinEgalite Aug 15, 2023
1979afa
refactor: user view and fix computation
MerlinEgalite Aug 15, 2023
fdb3d57
Merge branch 'feat/accrued-interests' of github.com:morpho-labs/morph…
MerlinEgalite Aug 15, 2023
84b8889
refactor: rename variables
MerlinEgalite Aug 15, 2023
516b728
chore: move files in a periphery folder
MerlinEgalite Aug 16, 2023
a1ab09c
refactor: renaming proposal
MerlinEgalite Aug 16, 2023
7b480c0
fix: correct naming for is auhtorized
MerlinEgalite Aug 16, 2023
0a5bd58
docs: add comments
MerlinEgalite Aug 16, 2023
38351ab
fix: iirm interface
MerlinEgalite Aug 16, 2023
53bb41f
refactor: harmonize morpho and lib
MerlinEgalite Aug 16, 2023
2736736
refactor: add slot to getters
MerlinEgalite Aug 16, 2023
31e1ef0
Merge pull request #307 from morpho-labs/feat/add-updated-getters
MerlinEgalite Aug 16, 2023
0f83222
Merge branch 'main' of github.com:morpho-labs/morpho-blue into feat/a…
MerlinEgalite Aug 16, 2023
8a3eec8
refactor: accrued interests -> interests in events
MerlinEgalite Aug 16, 2023
56329a3
refactor: renaming
MerlinEgalite Aug 16, 2023
8a5eb4e
refactor: interests -> interest
MerlinEgalite Aug 16, 2023
c567812
Merge branch 'main' of github.com:morpho-labs/morpho-blue into feat/a…
MerlinEgalite Aug 16, 2023
f162c8b
Merge branch 'main' of github.com:morpho-labs/morpho-blue into feat/a…
MerlinEgalite Aug 16, 2023
cf38cec
Merge branch 'feat/accrued-interests' of github.com:morpho-labs/morph…
MerlinEgalite Aug 16, 2023
1961394
Merge pull request #329 from morpho-labs/refactor/interest
MathisGD Aug 16, 2023
5085207
refactor: remove uselesss line spaces
MerlinEgalite Aug 16, 2023
dc82f52
test: add MorphoLib test
MerlinEgalite Aug 17, 2023
be93dd1
feat: add missing slot getters
MerlinEgalite Aug 17, 2023
e937427
test: add MorphoStorageLib tests
MerlinEgalite Aug 17, 2023
e35f684
refactor: apply suggestions
MerlinEgalite Aug 17, 2023
f9a46f4
docs: apply suggestion
MerlinEgalite Aug 17, 2023
cc78aed
refactor: bundle suggestions
MerlinEgalite Aug 17, 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
2 changes: 1 addition & 1 deletion src/interfaces/IIrm.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ pragma solidity >=0.5.0;
import {Market} from "./IBlue.sol";

interface IIrm {
function borrowRate(Market memory market) external returns (uint256);
function borrowRate(Market calldata market) external view returns (uint256);
}
52 changes: 52 additions & 0 deletions src/libraries/BlueLib.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

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

import {MarketLib} from "./MarketLib.sol";
import {BlueStorageLib} from "./BlueStorageLib.sol";
import {FixedPointMathLib} from "./FixedPointMathLib.sol";

library BlueLib {
using MarketLib for Market;
using FixedPointMathLib for uint256;

function accruedInterests(IBlue blue, Market memory market)
internal
view
returns (uint256 totalSupply, uint256 totalBorrow, uint256 totalSupplyShares)
{
Id id = market.id();

bytes32[] memory slots = new bytes32[](5);
slots[0] = BlueStorageLib.totalSupply(id);
slots[1] = BlueStorageLib.totalBorrow(id);
slots[2] = BlueStorageLib.totalSupplyShares(id);
slots[3] = BlueStorageLib.fee(id);
slots[4] = BlueStorageLib.lastUpdate(id);

bytes32[] memory values = blue.extsload(slots);
totalSupply = uint256(values[0]);
totalBorrow = uint256(values[1]);
totalSupplyShares = uint256(values[2]);
uint256 fee = uint256(values[3]);
uint256 lastUpdate = uint256(values[4]);

if (totalBorrow != 0) {
uint256 borrowRate = IIrm(market.irm).borrowRate(market);
uint256 interests = totalBorrow.wMulDown(borrowRate * (block.timestamp - lastUpdate));
MerlinEgalite marked this conversation as resolved.
Show resolved Hide resolved

totalBorrow += interests;
totalSupply += interests;
Rubilmax marked this conversation as resolved.
Show resolved Hide resolved

if (fee != 0) {
uint256 feeAmount = interests.wMulDown(fee);
// The fee amount is subtracted from the total supply in this calculation to compensate for the fact that total supply is already updated.
uint256 feeShares = feeAmount.mulDivDown(totalSupplyShares, totalSupply - feeAmount);

totalSupplyShares += feeShares;
}
}
}
}
77 changes: 77 additions & 0 deletions src/libraries/BlueStorageLib.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import {Id} from "./MarketLib.sol";

library BlueStorageLib {
uint256 internal constant OWNER_SLOT = 0;
uint256 internal constant FEE_RECIPIENT_SLOT = 1;
uint256 internal constant SUPPLY_SHARES_SLOT = 2;
uint256 internal constant BORROW_SHARES_SLOT = 3;
uint256 internal constant COLLATERAL_SLOT = 4;
uint256 internal constant TOTAL_SUPPLY_SLOT = 5;
uint256 internal constant TOTAL_SUPPLY_SHARES_SLOT = 6;
uint256 internal constant TOTAL_BORROW_SLOT = 7;
uint256 internal constant TOTAL_BORROW_SHARES_SLOT = 8;
uint256 internal constant LAST_UPDATE_SLOT = 9;
uint256 internal constant FEE_SLOT = 10;
uint256 internal constant IS_IRM_ENABLED_SLOT = 11;
uint256 internal constant IS_LLTV_ENABLED_SLOT = 12;
uint256 internal constant IS_AUTHORIZED_SLOT = 13;

function owner() internal pure returns (bytes32) {
return bytes32(OWNER_SLOT);
}

function feeRecipient() internal pure returns (bytes32) {
return bytes32(FEE_RECIPIENT_SLOT);
}

function supplyShares(Id id, address user) internal pure returns (bytes32) {
return keccak256(abi.encode(user, keccak256(abi.encode(id, SUPPLY_SHARES_SLOT))));
}

function borrowShares(Id id, address user) internal pure returns (bytes32) {
return keccak256(abi.encode(user, keccak256(abi.encode(id, BORROW_SHARES_SLOT))));
}

function collateral(Id id, address user) internal pure returns (bytes32) {
return keccak256(abi.encode(user, keccak256(abi.encode(id, COLLATERAL_SLOT))));
}

function totalSupply(Id id) internal pure returns (bytes32) {
return keccak256(abi.encode(id, TOTAL_SUPPLY_SLOT));
}

function totalSupplyShares(Id id) internal pure returns (bytes32) {
return keccak256(abi.encode(id, TOTAL_SUPPLY_SHARES_SLOT));
}

function totalBorrow(Id id) internal pure returns (bytes32) {
return keccak256(abi.encode(id, TOTAL_BORROW_SLOT));
}

function totalBorrowShares(Id id) internal pure returns (bytes32) {
return keccak256(abi.encode(id, TOTAL_BORROW_SHARES_SLOT));
}

function lastUpdate(Id id) internal pure returns (bytes32) {
return keccak256(abi.encode(id, LAST_UPDATE_SLOT));
}

function fee(Id id) internal pure returns (bytes32) {
return keccak256(abi.encode(id, FEE_SLOT));
}

function isIrmEnabled(address irm) internal pure returns (bytes32) {
return keccak256(abi.encode(irm, IS_IRM_ENABLED_SLOT));
}

function isLltvEnabled(uint256 lltv) internal pure returns (bytes32) {
return keccak256(abi.encode(lltv, IS_LLTV_ENABLED_SLOT));
}

function isApproved(address delegator, address manager) internal pure returns (bytes32) {
return keccak256(abi.encode(manager, keccak256(abi.encode(delegator, IS_AUTHORIZED_SLOT))));
}
}