From 2901c3666c5d057e903b02075ff373196a05cd5e Mon Sep 17 00:00:00 2001 From: MathisGD Date: Sun, 20 Aug 2023 12:03:28 +0200 Subject: [PATCH 1/6] test: utils lib --- test/forge/UtilsLib.t.sol | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/test/forge/UtilsLib.t.sol b/test/forge/UtilsLib.t.sol index 3607e8f89..1604a02e1 100644 --- a/test/forge/UtilsLib.t.sol +++ b/test/forge/UtilsLib.t.sol @@ -8,6 +8,21 @@ import "src/libraries/UtilsLib.sol"; contract UtilsLibTest is Test { using UtilsLib for uint256; + function testExactlyOneZeroTrue(uint256 x, uint256 y) public { + vm.assume((x > 0 && y == 0) || (x == 0 && y > 0)); + assertTrue(UtilsLib.exactlyOneZero(x, y)); + } + + function testExactlyOneZeroFalse(uint256 x, uint256 y) public { + vm.assume((x == 0 && y == 0) || (x > 0 && y > 0)); + assertFalse(UtilsLib.exactlyOneZero(x, y)); + } + + function testMin(uint256 x, uint256 y) public { + uint256 expectedMin = x < y ? x : y; + assertEq(UtilsLib.min(x, y), expectedMin); + } + function testToUint128(uint256 x) public { vm.assume(x <= type(uint128).max); assertEq(uint256(x.toUint128()), x); From 8262d862870b0e15394919e1e94a1b0636ab4214 Mon Sep 17 00:00:00 2001 From: MathisGD Date: Mon, 21 Aug 2023 10:19:04 +0200 Subject: [PATCH 2/6] test: improve UtilsLib testing --- test/forge/UtilsLib.t.sol | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/test/forge/UtilsLib.t.sol b/test/forge/UtilsLib.t.sol index 1604a02e1..09150fe44 100644 --- a/test/forge/UtilsLib.t.sol +++ b/test/forge/UtilsLib.t.sol @@ -8,19 +8,12 @@ import "src/libraries/UtilsLib.sol"; contract UtilsLibTest is Test { using UtilsLib for uint256; - function testExactlyOneZeroTrue(uint256 x, uint256 y) public { - vm.assume((x > 0 && y == 0) || (x == 0 && y > 0)); - assertTrue(UtilsLib.exactlyOneZero(x, y)); - } - - function testExactlyOneZeroFalse(uint256 x, uint256 y) public { - vm.assume((x == 0 && y == 0) || (x > 0 && y > 0)); - assertFalse(UtilsLib.exactlyOneZero(x, y)); + function testExactlyOneZero(uint256 x, uint256 y) public { + assertEq(UtilsLib.exactlyOneZero(x, y), (x > 0 && y == 0) || (x == 0 && y > 0)); } function testMin(uint256 x, uint256 y) public { - uint256 expectedMin = x < y ? x : y; - assertEq(UtilsLib.min(x, y), expectedMin); + assertEq(UtilsLib.min(x, y), x < y ? x : y); } function testToUint128(uint256 x) public { From 42fbd2065a2f4fb1e6719860bf720a296f0ee87d Mon Sep 17 00:00:00 2001 From: Rubilmax Date: Mon, 21 Aug 2023 10:26:17 +0200 Subject: [PATCH 3/6] refactor(balances): return total borrow shares --- ...hoBalancesLib.sol => MorphoBalanceLib.sol} | 49 ++++++++++--------- test/forge/periphery/MorphoBalanceLib.t.sol | 13 +++-- test/forge/periphery/MorphoLib.t.sol | 2 +- 3 files changed, 37 insertions(+), 27 deletions(-) rename src/libraries/periphery/{MorphoBalancesLib.sol => MorphoBalanceLib.sol} (66%) diff --git a/src/libraries/periphery/MorphoBalancesLib.sol b/src/libraries/periphery/MorphoBalanceLib.sol similarity index 66% rename from src/libraries/periphery/MorphoBalancesLib.sol rename to src/libraries/periphery/MorphoBalanceLib.sol index 4236fbef9..6c5b8380c 100644 --- a/src/libraries/periphery/MorphoBalancesLib.sol +++ b/src/libraries/periphery/MorphoBalanceLib.sol @@ -10,14 +10,14 @@ import {MarketLib} from "../MarketLib.sol"; import {SharesMathLib} from "../SharesMathLib.sol"; import {MorphoStorageLib} from "./MorphoStorageLib.sol"; -/// @title MorphoBalancesLib +/// @title MorphoBalanceLib /// @author Morpho Labs /// @custom:contact security@morpho.xyz /// @notice Helper library exposing getters with the expected value after interest accrual. /// @dev This library is not used in Morpho itself and is intended to be used by integrators. /// @dev The getter to retrieve the expected total borrow shares is not exposed because interest accrual does not apply to it. /// The value can be queried directly on Morpho using `totalBorrowShares`. -library MorphoBalancesLib { +library MorphoBalanceLib { using MathLib for uint256; using MorphoLib for IMorpho; using SharesMathLib for uint256; @@ -26,7 +26,12 @@ library MorphoBalancesLib { function expectedMarketBalances(IMorpho morpho, MarketParams memory marketParams) internal view - returns (uint256 totalSupplyAssets, uint256 toralBorrow, uint256 totalSupplyShares) + returns ( + uint256 totalSupplyAssets, + uint256 toralBorrowAssets, + uint256 totalSupplyShares, + uint256 totalBorrowShares + ) { Id id = marketParams.id(); @@ -38,27 +43,28 @@ library MorphoBalancesLib { bytes32[] memory values = morpho.extSloads(slots); totalSupplyAssets = uint128(uint256(values[0])); totalSupplyShares = uint256(values[0] >> 128); - toralBorrow = uint128(uint256(values[1])); + toralBorrowAssets = uint128(uint256(values[1])); + totalBorrowShares = uint256(values[1] >> 128); uint256 lastUpdate = uint128(uint256(values[2])); uint256 fee = uint256(values[2] >> 128); uint256 elapsed = block.timestamp - lastUpdate; - if (elapsed == 0) return (totalSupplyAssets, toralBorrow, totalSupplyShares); + if (elapsed == 0 || toralBorrowAssets == 0) { + return (totalSupplyAssets, toralBorrowAssets, totalSupplyShares, totalBorrowShares); + } - if (toralBorrow != 0) { - uint256 borrowRate = IIrm(marketParams.irm).borrowRateView(marketParams); - uint256 interest = toralBorrow.wMulDown(borrowRate.wTaylorCompounded(elapsed)); - toralBorrow += interest; - totalSupplyAssets += interest; + uint256 borrowRate = IIrm(marketParams.irm).borrowRateView(marketParams); + uint256 interest = toralBorrowAssets.wMulDown(borrowRate.wTaylorCompounded(elapsed)); + toralBorrowAssets += interest; + totalSupplyAssets += interest; - if (fee != 0) { - uint256 feeAmount = interest.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.toSharesDown(totalSupplyAssets - feeAmount, totalSupplyShares); + if (fee != 0) { + uint256 feeAmount = interest.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.toSharesDown(totalSupplyAssets - feeAmount, totalSupplyShares); - totalSupplyShares += feeShares; - } + totalSupplyShares += feeShares; } } @@ -67,7 +73,7 @@ library MorphoBalancesLib { view returns (uint256 totalSupplyAssets) { - (totalSupplyAssets,,) = expectedMarketBalances(morpho, marketParams); + (totalSupplyAssets,,,) = expectedMarketBalances(morpho, marketParams); } function expectedTotalBorrow(IMorpho morpho, MarketParams memory marketParams) @@ -75,7 +81,7 @@ library MorphoBalancesLib { view returns (uint256 totalBorrowAssets) { - (, totalBorrowAssets,) = expectedMarketBalances(morpho, marketParams); + (, totalBorrowAssets,,) = expectedMarketBalances(morpho, marketParams); } function expectedTotalSupplyShares(IMorpho morpho, MarketParams memory marketParams) @@ -83,7 +89,7 @@ library MorphoBalancesLib { view returns (uint256 totalSupplyShares) { - (,, totalSupplyShares) = expectedMarketBalances(morpho, marketParams); + (,, totalSupplyShares,) = expectedMarketBalances(morpho, marketParams); } /// @dev Warning: It does not work for `feeRecipient` because their supply shares increase is not taken into account. @@ -94,7 +100,7 @@ library MorphoBalancesLib { { Id id = marketParams.id(); uint256 supplyShares = morpho.supplyShares(id, user); - (uint256 totalSupplyAssets,, uint256 totalSupplyShares) = expectedMarketBalances(morpho, marketParams); + (uint256 totalSupplyAssets,, uint256 totalSupplyShares,) = expectedMarketBalances(morpho, marketParams); return supplyShares.toAssetsDown(totalSupplyAssets, totalSupplyShares); } @@ -106,8 +112,7 @@ library MorphoBalancesLib { { Id id = marketParams.id(); uint256 borrowShares = morpho.borrowShares(id, user); - uint256 totalBorrowShares = morpho.totalBorrowShares(id); - (, uint256 totalBorrowAssets,) = expectedMarketBalances(morpho, marketParams); + (, uint256 totalBorrowAssets,, uint256 totalBorrowShares) = expectedMarketBalances(morpho, marketParams); return borrowShares.toAssetsUp(totalBorrowAssets, totalBorrowShares); } diff --git a/test/forge/periphery/MorphoBalanceLib.t.sol b/test/forge/periphery/MorphoBalanceLib.t.sol index aff6b41f9..16c913481 100644 --- a/test/forge/periphery/MorphoBalanceLib.t.sol +++ b/test/forge/periphery/MorphoBalanceLib.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; -import {MorphoBalancesLib} from "src/libraries/periphery/MorphoBalancesLib.sol"; +import {MorphoBalanceLib} from "src/libraries/periphery/MorphoBalanceLib.sol"; import "../BaseTest.sol"; @@ -9,21 +9,26 @@ contract MorphoBalanceLibTest is BaseTest { using MathLib for uint256; using MorphoLib for Morpho; using SharesMathLib for uint256; - using MorphoBalancesLib for Morpho; + using MorphoBalanceLib for Morpho; function testVirtualAccrueInterest(uint256 amountSupplied, uint256 amountBorrowed, uint256 timeElapsed, uint256 fee) public { _generatePendingInterest(amountSupplied, amountBorrowed, timeElapsed, fee); - (uint256 virtualTotalSupply, uint256 virtualTotalBorrow, uint256 virtualTotalSupplyShares) = - morpho.expectedMarketBalances(market); + ( + uint256 virtualTotalSupply, + uint256 virtualTotalBorrow, + uint256 virtualTotalSupplyShares, + uint256 virtualTotalBorrowShares + ) = morpho.expectedMarketBalances(market); morpho.accrueInterest(market); assertEq(virtualTotalSupply, morpho.totalSupplyAssets(id), "total supply"); assertEq(virtualTotalBorrow, morpho.totalBorrowAssets(id), "total borrow"); assertEq(virtualTotalSupplyShares, morpho.totalSupplyShares(id), "total supply shares"); + assertEq(virtualTotalBorrowShares, morpho.totalBorrowShares(id), "total borrrow shares"); } function testExpectedTotalSupply(uint256 amountSupplied, uint256 amountBorrowed, uint256 timeElapsed, uint256 fee) diff --git a/test/forge/periphery/MorphoLib.t.sol b/test/forge/periphery/MorphoLib.t.sol index 034183043..4281da2d6 100644 --- a/test/forge/periphery/MorphoLib.t.sol +++ b/test/forge/periphery/MorphoLib.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; -import {MorphoBalancesLib} from "src/libraries/periphery/MorphoBalancesLib.sol"; +import {MorphoBalanceLib} from "src/libraries/periphery/MorphoBalanceLib.sol"; import "../BaseTest.sol"; From 859b0d08fb4e88d96767d7d70532b8620941cbb8 Mon Sep 17 00:00:00 2001 From: Romain Milon Date: Mon, 21 Aug 2023 11:17:56 +0200 Subject: [PATCH 4/6] refactor(balances-test): remove typo Co-authored-by: MathisGD <74971347+MathisGD@users.noreply.github.com> Signed-off-by: Romain Milon --- test/forge/periphery/MorphoBalanceLib.t.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/forge/periphery/MorphoBalanceLib.t.sol b/test/forge/periphery/MorphoBalanceLib.t.sol index 16c913481..9c1591794 100644 --- a/test/forge/periphery/MorphoBalanceLib.t.sol +++ b/test/forge/periphery/MorphoBalanceLib.t.sol @@ -28,7 +28,7 @@ contract MorphoBalanceLibTest is BaseTest { assertEq(virtualTotalSupply, morpho.totalSupplyAssets(id), "total supply"); assertEq(virtualTotalBorrow, morpho.totalBorrowAssets(id), "total borrow"); assertEq(virtualTotalSupplyShares, morpho.totalSupplyShares(id), "total supply shares"); - assertEq(virtualTotalBorrowShares, morpho.totalBorrowShares(id), "total borrrow shares"); + assertEq(virtualTotalBorrowShares, morpho.totalBorrowShares(id), "total borrow shares"); } function testExpectedTotalSupply(uint256 amountSupplied, uint256 amountBorrowed, uint256 timeElapsed, uint256 fee) From 05d31f0883ea65b244906e650ec8f7168e8f94fc Mon Sep 17 00:00:00 2001 From: Rubilmax Date: Mon, 21 Aug 2023 11:22:38 +0200 Subject: [PATCH 5/6] refactor(balance-lib): avoid named return --- src/libraries/periphery/MorphoBalanceLib.sol | 28 +++++++++----------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/src/libraries/periphery/MorphoBalanceLib.sol b/src/libraries/periphery/MorphoBalanceLib.sol index 6c5b8380c..15a950164 100644 --- a/src/libraries/periphery/MorphoBalanceLib.sol +++ b/src/libraries/periphery/MorphoBalanceLib.sol @@ -50,21 +50,19 @@ library MorphoBalanceLib { uint256 elapsed = block.timestamp - lastUpdate; - if (elapsed == 0 || toralBorrowAssets == 0) { - return (totalSupplyAssets, toralBorrowAssets, totalSupplyShares, totalBorrowShares); - } - - uint256 borrowRate = IIrm(marketParams.irm).borrowRateView(marketParams); - uint256 interest = toralBorrowAssets.wMulDown(borrowRate.wTaylorCompounded(elapsed)); - toralBorrowAssets += interest; - totalSupplyAssets += interest; - - if (fee != 0) { - uint256 feeAmount = interest.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.toSharesDown(totalSupplyAssets - feeAmount, totalSupplyShares); - - totalSupplyShares += feeShares; + if (elapsed != 0 && toralBorrowAssets != 0) { + uint256 borrowRate = IIrm(marketParams.irm).borrowRateView(marketParams); + uint256 interest = toralBorrowAssets.wMulDown(borrowRate.wTaylorCompounded(elapsed)); + toralBorrowAssets += interest; + totalSupplyAssets += interest; + + if (fee != 0) { + uint256 feeAmount = interest.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.toSharesDown(totalSupplyAssets - feeAmount, totalSupplyShares); + + totalSupplyShares += feeShares; + } } } From 0eebdebfe239f54c55c7f7f7ae439800a3f794d0 Mon Sep 17 00:00:00 2001 From: Rubilmax Date: Mon, 21 Aug 2023 12:08:04 +0200 Subject: [PATCH 6/6] refactor(balances-lib): use plural --- .../{MorphoBalanceLib.sol => MorphoBalancesLib.sol} | 4 ++-- .../{MorphoBalanceLib.t.sol => MorphoBalancesLib.t.sol} | 6 +++--- test/forge/periphery/MorphoLib.t.sol | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) rename src/libraries/periphery/{MorphoBalanceLib.sol => MorphoBalancesLib.sol} (98%) rename test/forge/periphery/{MorphoBalanceLib.t.sol => MorphoBalancesLib.t.sol} (96%) diff --git a/src/libraries/periphery/MorphoBalanceLib.sol b/src/libraries/periphery/MorphoBalancesLib.sol similarity index 98% rename from src/libraries/periphery/MorphoBalanceLib.sol rename to src/libraries/periphery/MorphoBalancesLib.sol index 15a950164..e783aec90 100644 --- a/src/libraries/periphery/MorphoBalanceLib.sol +++ b/src/libraries/periphery/MorphoBalancesLib.sol @@ -10,14 +10,14 @@ import {MarketLib} from "../MarketLib.sol"; import {SharesMathLib} from "../SharesMathLib.sol"; import {MorphoStorageLib} from "./MorphoStorageLib.sol"; -/// @title MorphoBalanceLib +/// @title MorphoBalancesLib /// @author Morpho Labs /// @custom:contact security@morpho.xyz /// @notice Helper library exposing getters with the expected value after interest accrual. /// @dev This library is not used in Morpho itself and is intended to be used by integrators. /// @dev The getter to retrieve the expected total borrow shares is not exposed because interest accrual does not apply to it. /// The value can be queried directly on Morpho using `totalBorrowShares`. -library MorphoBalanceLib { +library MorphoBalancesLib { using MathLib for uint256; using MorphoLib for IMorpho; using SharesMathLib for uint256; diff --git a/test/forge/periphery/MorphoBalanceLib.t.sol b/test/forge/periphery/MorphoBalancesLib.t.sol similarity index 96% rename from test/forge/periphery/MorphoBalanceLib.t.sol rename to test/forge/periphery/MorphoBalancesLib.t.sol index 9c1591794..52e9d3374 100644 --- a/test/forge/periphery/MorphoBalanceLib.t.sol +++ b/test/forge/periphery/MorphoBalancesLib.t.sol @@ -1,15 +1,15 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; -import {MorphoBalanceLib} from "src/libraries/periphery/MorphoBalanceLib.sol"; +import {MorphoBalancesLib} from "src/libraries/periphery/MorphoBalancesLib.sol"; import "../BaseTest.sol"; -contract MorphoBalanceLibTest is BaseTest { +contract MorphoBalancesLibTest is BaseTest { using MathLib for uint256; using MorphoLib for Morpho; using SharesMathLib for uint256; - using MorphoBalanceLib for Morpho; + using MorphoBalancesLib for Morpho; function testVirtualAccrueInterest(uint256 amountSupplied, uint256 amountBorrowed, uint256 timeElapsed, uint256 fee) public diff --git a/test/forge/periphery/MorphoLib.t.sol b/test/forge/periphery/MorphoLib.t.sol index 4281da2d6..034183043 100644 --- a/test/forge/periphery/MorphoLib.t.sol +++ b/test/forge/periphery/MorphoLib.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; -import {MorphoBalanceLib} from "src/libraries/periphery/MorphoBalanceLib.sol"; +import {MorphoBalancesLib} from "src/libraries/periphery/MorphoBalancesLib.sol"; import "../BaseTest.sol";