From d164f11e35da4c9052f93962c3554c130db81067 Mon Sep 17 00:00:00 2001 From: MathisGD Date: Tue, 8 Aug 2023 17:44:26 +0200 Subject: [PATCH 1/5] refactor: various changes in libraries --- src/Blue.sol | 89 ++++++++------- src/libraries/BlueLib.sol | 4 +- src/libraries/{Errors.sol => ErrorsLib.sol} | 2 +- src/libraries/FixedPointMathLib.sol | 34 +++--- .../{SharesMath.sol => SharesMathLib.sol} | 2 +- test/forge/Blue.t.sol | 102 +++++++++--------- .../{SharesMath.t.sol => SharesMathLib.t.sol} | 10 +- 7 files changed, 120 insertions(+), 123 deletions(-) rename src/libraries/{Errors.sol => ErrorsLib.sol} (98%) rename src/libraries/{SharesMath.sol => SharesMathLib.sol} (99%) rename test/forge/{SharesMath.t.sol => SharesMathLib.t.sol} (77%) diff --git a/src/Blue.sol b/src/Blue.sol index 660ffd91c..8dcf96614 100644 --- a/src/Blue.sol +++ b/src/Blue.sol @@ -13,11 +13,11 @@ import {IERC20} from "./interfaces/IERC20.sol"; import {IOracle} from "./interfaces/IOracle.sol"; import {Id, Market, Signature, IBlue} from "./interfaces/IBlue.sol"; -import {Errors} from "./libraries/Errors.sol"; -import {SharesMath} from "./libraries/SharesMath.sol"; -import {FixedPointMathLib} from "./libraries/FixedPointMathLib.sol"; +import {ErrorsLib} from "./libraries/ErrorsLib.sol"; import {MarketLib} from "./libraries/MarketLib.sol"; +import {SharesMathLib} from "./libraries/SharesMathLib.sol"; import {SafeTransferLib} from "./libraries/SafeTransferLib.sol"; +import {FixedPointMathLib, WAD} from "./libraries/FixedPointMathLib.sol"; uint256 constant MAX_FEE = 0.25e18; uint256 constant ALPHA = 0.5e18; @@ -30,10 +30,10 @@ bytes32 constant AUTHORIZATION_TYPEHASH = keccak256("Authorization(address authorizer,address authorized,bool isAuthorized,uint256 nonce,uint256 deadline)"); contract Blue is IBlue { - using SharesMath for uint256; - using FixedPointMathLib for uint256; - using SafeTransferLib for IERC20; using MarketLib for Market; + using SharesMathLib for uint256; + using SafeTransferLib for IERC20; + using FixedPointMathLib for uint256; // Immutables. @@ -83,7 +83,7 @@ contract Blue is IBlue { // Modifiers. modifier onlyOwner() { - require(msg.sender == owner, Errors.NOT_OWNER); + require(msg.sender == owner, ErrorsLib.NOT_OWNER); _; } @@ -102,7 +102,7 @@ contract Blue is IBlue { } function enableLltv(uint256 lltv) external onlyOwner { - require(lltv < FixedPointMathLib.WAD, Errors.LLTV_TOO_HIGH); + require(lltv < WAD, ErrorsLib.LLTV_TOO_HIGH); isLltvEnabled[lltv] = true; emit EnableLltv(lltv); @@ -111,8 +111,8 @@ contract Blue is IBlue { /// @notice It is the owner's responsibility to ensure a fee recipient is set before setting a non-zero fee. function setFee(Market memory market, uint256 newFee) external onlyOwner { Id id = market.id(); - require(lastUpdate[id] != 0, Errors.MARKET_NOT_CREATED); - require(newFee <= MAX_FEE, Errors.MAX_FEE_EXCEEDED); + require(lastUpdate[id] != 0, ErrorsLib.MARKET_NOT_CREATED); + require(newFee <= MAX_FEE, ErrorsLib.MAX_FEE_EXCEEDED); fee[id] = newFee; emit SetFee(id, newFee); @@ -128,9 +128,9 @@ contract Blue is IBlue { function createMarket(Market memory market) external { Id id = market.id(); - require(isIrmEnabled[market.irm], Errors.IRM_NOT_ENABLED); - require(isLltvEnabled[market.lltv], Errors.LLTV_NOT_ENABLED); - require(lastUpdate[id] == 0, Errors.MARKET_CREATED); + require(isIrmEnabled[market.irm], ErrorsLib.IRM_NOT_ENABLED); + require(isLltvEnabled[market.lltv], ErrorsLib.LLTV_NOT_ENABLED); + require(lastUpdate[id] == 0, ErrorsLib.MARKET_CREATED); lastUpdate[id] = block.timestamp; emit CreateMarket(id, market); @@ -140,9 +140,9 @@ contract Blue is IBlue { function supply(Market memory market, uint256 amount, address onBehalf, bytes calldata data) external { Id id = market.id(); - require(lastUpdate[id] != 0, Errors.MARKET_NOT_CREATED); - require(amount != 0, Errors.ZERO_AMOUNT); - require(onBehalf != address(0), Errors.ZERO_ADDRESS); + require(lastUpdate[id] != 0, ErrorsLib.MARKET_NOT_CREATED); + require(amount != 0, ErrorsLib.ZERO_AMOUNT); + require(onBehalf != address(0), ErrorsLib.ZERO_ADDRESS); _accrueInterests(market, id); @@ -161,11 +161,11 @@ contract Blue is IBlue { function withdraw(Market memory market, uint256 shares, address onBehalf, address receiver) external { Id id = market.id(); - require(lastUpdate[id] != 0, Errors.MARKET_NOT_CREATED); - require(shares != 0, Errors.ZERO_SHARES); + require(lastUpdate[id] != 0, ErrorsLib.MARKET_NOT_CREATED); + require(shares != 0, ErrorsLib.ZERO_SHARES); // No need to verify that onBehalf != address(0) thanks to the authorization check. - require(receiver != address(0), Errors.ZERO_ADDRESS); - require(_isSenderAuthorized(onBehalf), Errors.UNAUTHORIZED); + require(receiver != address(0), ErrorsLib.ZERO_ADDRESS); + require(_isSenderAuthorized(onBehalf), ErrorsLib.UNAUTHORIZED); _accrueInterests(market, id); @@ -177,7 +177,7 @@ contract Blue is IBlue { emit Withdraw(id, msg.sender, onBehalf, receiver, amount, shares); - require(totalBorrow[id] <= totalSupply[id], Errors.INSUFFICIENT_LIQUIDITY); + require(totalBorrow[id] <= totalSupply[id], ErrorsLib.INSUFFICIENT_LIQUIDITY); IERC20(market.borrowableAsset).safeTransfer(receiver, amount); } @@ -186,11 +186,11 @@ contract Blue is IBlue { function borrow(Market memory market, uint256 amount, address onBehalf, address receiver) external { Id id = market.id(); - require(lastUpdate[id] != 0, Errors.MARKET_NOT_CREATED); - require(amount != 0, Errors.ZERO_AMOUNT); + require(lastUpdate[id] != 0, ErrorsLib.MARKET_NOT_CREATED); + require(amount != 0, ErrorsLib.ZERO_AMOUNT); // No need to verify that onBehalf != address(0) thanks to the authorization check. - require(receiver != address(0), Errors.ZERO_ADDRESS); - require(_isSenderAuthorized(onBehalf), Errors.UNAUTHORIZED); + require(receiver != address(0), ErrorsLib.ZERO_ADDRESS); + require(_isSenderAuthorized(onBehalf), ErrorsLib.UNAUTHORIZED); _accrueInterests(market, id); @@ -202,17 +202,17 @@ contract Blue is IBlue { emit Borrow(id, msg.sender, onBehalf, receiver, amount, shares); - require(_isHealthy(market, id, onBehalf), Errors.INSUFFICIENT_COLLATERAL); - require(totalBorrow[id] <= totalSupply[id], Errors.INSUFFICIENT_LIQUIDITY); + require(_isHealthy(market, id, onBehalf), ErrorsLib.INSUFFICIENT_COLLATERAL); + require(totalBorrow[id] <= totalSupply[id], ErrorsLib.INSUFFICIENT_LIQUIDITY); IERC20(market.borrowableAsset).safeTransfer(receiver, amount); } function repay(Market memory market, uint256 shares, address onBehalf, bytes calldata data) external { Id id = market.id(); - require(lastUpdate[id] != 0, Errors.MARKET_NOT_CREATED); - require(shares != 0, Errors.ZERO_SHARES); - require(onBehalf != address(0), Errors.ZERO_ADDRESS); + require(lastUpdate[id] != 0, ErrorsLib.MARKET_NOT_CREATED); + require(shares != 0, ErrorsLib.ZERO_SHARES); + require(onBehalf != address(0), ErrorsLib.ZERO_ADDRESS); _accrueInterests(market, id); @@ -234,9 +234,9 @@ contract Blue is IBlue { /// @dev Don't accrue interests because it's not required and it saves gas. function supplyCollateral(Market memory market, uint256 amount, address onBehalf, bytes calldata data) external { Id id = market.id(); - require(lastUpdate[id] != 0, Errors.MARKET_NOT_CREATED); - require(amount != 0, Errors.ZERO_AMOUNT); - require(onBehalf != address(0), Errors.ZERO_ADDRESS); + require(lastUpdate[id] != 0, ErrorsLib.MARKET_NOT_CREATED); + require(amount != 0, ErrorsLib.ZERO_AMOUNT); + require(onBehalf != address(0), ErrorsLib.ZERO_ADDRESS); // Don't accrue interests because it's not required and it saves gas. @@ -251,11 +251,11 @@ contract Blue is IBlue { function withdrawCollateral(Market memory market, uint256 amount, address onBehalf, address receiver) external { Id id = market.id(); - require(lastUpdate[id] != 0, Errors.MARKET_NOT_CREATED); - require(amount != 0, Errors.ZERO_AMOUNT); + require(lastUpdate[id] != 0, ErrorsLib.MARKET_NOT_CREATED); + require(amount != 0, ErrorsLib.ZERO_AMOUNT); // No need to verify that onBehalf != address(0) thanks to the authorization check. - require(receiver != address(0), Errors.ZERO_ADDRESS); - require(_isSenderAuthorized(onBehalf), Errors.UNAUTHORIZED); + require(receiver != address(0), ErrorsLib.ZERO_ADDRESS); + require(_isSenderAuthorized(onBehalf), ErrorsLib.UNAUTHORIZED); _accrueInterests(market, id); @@ -263,7 +263,7 @@ contract Blue is IBlue { emit WithdrawCollateral(id, msg.sender, onBehalf, receiver, amount); - require(_isHealthy(market, id, onBehalf), Errors.INSUFFICIENT_COLLATERAL); + require(_isHealthy(market, id, onBehalf), ErrorsLib.INSUFFICIENT_COLLATERAL); IERC20(market.collateralAsset).safeTransfer(receiver, amount); } @@ -272,19 +272,18 @@ contract Blue is IBlue { function liquidate(Market memory market, address borrower, uint256 seized, bytes calldata data) external { Id id = market.id(); - require(lastUpdate[id] != 0, Errors.MARKET_NOT_CREATED); - require(seized != 0, Errors.ZERO_AMOUNT); + require(lastUpdate[id] != 0, ErrorsLib.MARKET_NOT_CREATED); + require(seized != 0, ErrorsLib.ZERO_AMOUNT); _accrueInterests(market, id); uint256 collateralPrice = IOracle(market.collateralOracle).price(); uint256 borrowablePrice = IOracle(market.borrowableOracle).price(); - require(!_isHealthy(market, id, borrower, collateralPrice, borrowablePrice), Errors.HEALTHY_POSITION); + require(!_isHealthy(market, id, borrower, collateralPrice, borrowablePrice), ErrorsLib.HEALTHY_POSITION); // The liquidation incentive is 1 + ALPHA * (1 / LLTV - 1). - uint256 incentive = FixedPointMathLib.WAD - + ALPHA.mulWadDown(FixedPointMathLib.WAD.divWadDown(market.lltv) - FixedPointMathLib.WAD); + uint256 incentive = WAD + ALPHA.mulWadDown(WAD.divWadDown(market.lltv) - WAD); uint256 repaid = seized.mulWadUp(collateralPrice).divWadUp(incentive).divWadUp(borrowablePrice); uint256 repaidShares = repaid.toSharesDown(totalBorrow[id], totalBorrowShares[id]); @@ -336,7 +335,7 @@ contract Blue is IBlue { uint256 deadline, Signature calldata signature ) external { - require(block.timestamp < deadline, Errors.SIGNATURE_EXPIRED); + require(block.timestamp < deadline, ErrorsLib.SIGNATURE_EXPIRED); uint256 usedNonce = nonce[authorizer]++; bytes32 hashStruct = @@ -344,7 +343,7 @@ contract Blue is IBlue { bytes32 digest = keccak256(abi.encodePacked("\x19\x01", DOMAIN_SEPARATOR, hashStruct)); address signatory = ecrecover(digest, signature.v, signature.r, signature.s); - require(signatory != address(0) && authorizer == signatory, Errors.INVALID_SIGNATURE); + require(signatory != address(0) && authorizer == signatory, ErrorsLib.INVALID_SIGNATURE); emit IncrementNonce(msg.sender, authorizer, usedNonce); diff --git a/src/libraries/BlueLib.sol b/src/libraries/BlueLib.sol index 580c13e53..a14bfaf9f 100644 --- a/src/libraries/BlueLib.sol +++ b/src/libraries/BlueLib.sol @@ -4,11 +4,11 @@ pragma solidity ^0.8.0; import {Id, Market, IBlue} from "../interfaces/IBlue.sol"; import {MarketLib} from "./MarketLib.sol"; -import {SharesMath} from "./SharesMath.sol"; +import {SharesMathLib} from "./SharesMathLib.sol"; library BlueLib { using MarketLib for Market; - using SharesMath for uint256; + using SharesMathLib for uint256; function withdrawAmount(IBlue blue, Market memory market, uint256 amount, address onBehalf, address receiver) internal diff --git a/src/libraries/Errors.sol b/src/libraries/ErrorsLib.sol similarity index 98% rename from src/libraries/Errors.sol rename to src/libraries/ErrorsLib.sol index d4be41a56..08c5513ad 100644 --- a/src/libraries/Errors.sol +++ b/src/libraries/ErrorsLib.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; -library Errors { +library ErrorsLib { string internal constant NOT_OWNER = "not owner"; string internal constant LLTV_TOO_HIGH = "LLTV too high"; diff --git a/src/libraries/FixedPointMathLib.sol b/src/libraries/FixedPointMathLib.sol index 8afddd034..63a7bb0f1 100644 --- a/src/libraries/FixedPointMathLib.sol +++ b/src/libraries/FixedPointMathLib.sol @@ -1,38 +1,35 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; -/// @notice Arithmetic library with operations for fixed-point numbers. -/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/FixedPointMathLib.sol) -/// @author Inspired by USM (https://github.com/usmfum/USM/blob/master/contracts/WadMath.sol) -library FixedPointMathLib { - /*////////////////////////////////////////////////////////////// - SIMPLIFIED FIXED POINT OPERATIONS - //////////////////////////////////////////////////////////////*/ - - uint256 internal constant MAX_UINT256 = 2 ** 256 - 1; +uint256 constant WAD = 1e18; - uint256 internal constant WAD = 1e18; // The scalar of ETH and most ERC20s. +/// @notice Fixed-point arithmetic library. +/// @dev Greatly inspired by Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/FixedPointMathLib.sol) +/// and by USM (https://github.com/usmfum/USM/blob/master/contracts/WadMath.sol) +library FixedPointMathLib { + uint256 private constant MAX_UINT256 = 2 ** 256 - 1; + /// @dev (x * y) / WAD rounded down. function mulWadDown(uint256 x, uint256 y) internal pure returns (uint256) { - return mulDivDown(x, y, WAD); // Equivalent to (x * y) / WAD rounded down. + return mulDivDown(x, y, WAD); } + /// @dev (x * y) / WAD rounded up. function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256) { - return mulDivUp(x, y, WAD); // Equivalent to (x * y) / WAD rounded up. + return mulDivUp(x, y, WAD); } + /// @dev (x * WAD) / y rounded down. function divWadDown(uint256 x, uint256 y) internal pure returns (uint256) { - return mulDivDown(x, WAD, y); // Equivalent to (x * WAD) / y rounded down. + return mulDivDown(x, WAD, y); } + /// @dev (x * WAD) / y rounded up. function divWadUp(uint256 x, uint256 y) internal pure returns (uint256) { - return mulDivUp(x, WAD, y); // Equivalent to (x * WAD) / y rounded up. + return mulDivUp(x, WAD, y); } - /*////////////////////////////////////////////////////////////// - LOW LEVEL FIXED POINT OPERATIONS - //////////////////////////////////////////////////////////////*/ - + /// @dev (x * y) / denominator rounded down. function mulDivDown(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { @@ -44,6 +41,7 @@ library FixedPointMathLib { } } + /// @dev (x * y) / denominator rounded up. function mulDivUp(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { diff --git a/src/libraries/SharesMath.sol b/src/libraries/SharesMathLib.sol similarity index 99% rename from src/libraries/SharesMath.sol rename to src/libraries/SharesMathLib.sol index 9f1dab24f..f039a7ef3 100644 --- a/src/libraries/SharesMath.sol +++ b/src/libraries/SharesMathLib.sol @@ -5,7 +5,7 @@ import {FixedPointMathLib} from "./FixedPointMathLib.sol"; /// @notice Shares management library. /// @dev This implementation mitigates share price manipulations, using OpenZeppelin's method of virtual shares: https://docs.openzeppelin.com/contracts/4.x/erc4626#inflation-attack. -library SharesMath { +library SharesMathLib { using FixedPointMathLib for uint256; uint256 internal constant VIRTUAL_SHARES = 1e18; diff --git a/test/forge/Blue.t.sol b/test/forge/Blue.t.sol index 1001c7753..269f6cbbf 100644 --- a/test/forge/Blue.t.sol +++ b/test/forge/Blue.t.sol @@ -7,7 +7,7 @@ import "forge-std/console.sol"; import {SigUtils} from "./helpers/SigUtils.sol"; import "src/Blue.sol"; -import {SharesMath} from "src/libraries/SharesMath.sol"; +import {SharesMathLib} from "src/libraries/SharesMathLib.sol"; import {BlueLib} from "src/libraries/BlueLib.sol"; import { IBlueLiquidateCallback, @@ -28,7 +28,7 @@ contract BlueTest is { using BlueLib for IBlue; using MarketLib for Market; - using SharesMath for uint256; + using SharesMathLib for uint256; using stdStorage for StdStorage; using FixedPointMathLib for uint256; @@ -158,7 +158,7 @@ contract BlueTest is Blue blue2 = new Blue(OWNER); vm.prank(attacker); - vm.expectRevert(bytes(Errors.NOT_OWNER)); + vm.expectRevert(bytes(ErrorsLib.NOT_OWNER)); blue2.setOwner(newOwner); } @@ -166,7 +166,7 @@ contract BlueTest is vm.assume(attacker != blue.owner()); vm.prank(attacker); - vm.expectRevert(bytes(Errors.NOT_OWNER)); + vm.expectRevert(bytes(ErrorsLib.NOT_OWNER)); blue.enableIrm(newIrm); } @@ -190,7 +190,7 @@ contract BlueTest is vm.assume(marketFuzz.irm != address(irm)); vm.prank(OWNER); - vm.expectRevert(bytes(Errors.IRM_NOT_ENABLED)); + vm.expectRevert(bytes(ErrorsLib.IRM_NOT_ENABLED)); blue.createMarket(marketFuzz); } @@ -198,12 +198,12 @@ contract BlueTest is vm.assume(attacker != OWNER); vm.prank(attacker); - vm.expectRevert(bytes(Errors.NOT_OWNER)); + vm.expectRevert(bytes(ErrorsLib.NOT_OWNER)); blue.enableLltv(newLltv); } function testEnableLltv(uint256 newLltv) public { - newLltv = bound(newLltv, 0, FixedPointMathLib.WAD - 1); + newLltv = bound(newLltv, 0, WAD - 1); vm.prank(OWNER); blue.enableLltv(newLltv); @@ -212,10 +212,10 @@ contract BlueTest is } function testEnableLltvShouldFailWhenLltvTooHigh(uint256 newLltv) public { - newLltv = bound(newLltv, FixedPointMathLib.WAD, type(uint256).max); + newLltv = bound(newLltv, WAD, type(uint256).max); vm.prank(OWNER); - vm.expectRevert(bytes(Errors.LLTV_TOO_HIGH)); + vm.expectRevert(bytes(ErrorsLib.LLTV_TOO_HIGH)); blue.enableLltv(newLltv); } @@ -232,24 +232,24 @@ contract BlueTest is fee = bound(fee, MAX_FEE + 1, type(uint256).max); vm.prank(OWNER); - vm.expectRevert(bytes(Errors.MAX_FEE_EXCEEDED)); + vm.expectRevert(bytes(ErrorsLib.MAX_FEE_EXCEEDED)); blue.setFee(market, fee); } function testSetFeeShouldRevertIfMarketNotCreated(Market memory marketFuzz, uint256 fee) public { vm.assume(neq(marketFuzz, market)); - fee = bound(fee, 0, FixedPointMathLib.WAD); + fee = bound(fee, 0, WAD); vm.prank(OWNER); - vm.expectRevert(bytes(Errors.MARKET_NOT_CREATED)); + vm.expectRevert(bytes(ErrorsLib.MARKET_NOT_CREATED)); blue.setFee(marketFuzz, fee); } function testSetFeeShouldRevertIfNotOwner(uint256 fee, address caller) public { vm.assume(caller != OWNER); - fee = bound(fee, 0, FixedPointMathLib.WAD); + fee = bound(fee, 0, WAD); - vm.expectRevert(bytes(Errors.NOT_OWNER)); + vm.expectRevert(bytes(ErrorsLib.NOT_OWNER)); blue.setFee(market, fee); } @@ -263,7 +263,7 @@ contract BlueTest is function testSetFeeRecipientShouldRevertIfNotOwner(address caller, address recipient) public { vm.assume(caller != OWNER); - vm.expectRevert(bytes(Errors.NOT_OWNER)); + vm.expectRevert(bytes(ErrorsLib.NOT_OWNER)); vm.prank(caller); blue.setFeeRecipient(recipient); } @@ -311,7 +311,7 @@ contract BlueTest is marketFuzz.irm = address(irm); vm.prank(OWNER); - vm.expectRevert(bytes(Errors.LLTV_NOT_ENABLED)); + vm.expectRevert(bytes(ErrorsLib.LLTV_NOT_ENABLED)); blue.createMarket(marketFuzz); } @@ -323,7 +323,7 @@ contract BlueTest is borrowableAsset.setBalance(address(this), amount); blue.supply(market, amount, onBehalf, hex""); - assertEq(blue.supplyShares(id, onBehalf), amount * SharesMath.VIRTUAL_SHARES, "supply share"); + assertEq(blue.supplyShares(id, onBehalf), amount * SharesMathLib.VIRTUAL_SHARES, "supply share"); assertEq(borrowableAsset.balanceOf(onBehalf), 0, "lender balance"); assertEq(borrowableAsset.balanceOf(address(blue)), amount, "blue balance"); } @@ -339,7 +339,7 @@ contract BlueTest is if (amountBorrowed > amountLent) { vm.prank(BORROWER); - vm.expectRevert(bytes(Errors.INSUFFICIENT_LIQUIDITY)); + vm.expectRevert(bytes(ErrorsLib.INSUFFICIENT_LIQUIDITY)); blue.borrow(market, amountBorrowed, BORROWER, receiver); return; } @@ -347,7 +347,7 @@ contract BlueTest is vm.prank(BORROWER); blue.borrow(market, amountBorrowed, BORROWER, receiver); - assertEq(blue.borrowShares(id, BORROWER), amountBorrowed * SharesMath.VIRTUAL_SHARES, "borrow share"); + assertEq(blue.borrowShares(id, BORROWER), amountBorrowed * SharesMathLib.VIRTUAL_SHARES, "borrow share"); assertEq(borrowableAsset.balanceOf(receiver), amountBorrowed, "receiver balance"); assertEq(borrowableAsset.balanceOf(address(blue)), amountLent - amountBorrowed, "blue balance"); } @@ -387,7 +387,7 @@ contract BlueTest is blue.withdraw(market, sharesWithdrawn, address(this), receiver); return; } else if (amountWithdrawn > totalSupplyBefore - amountBorrowed) { - vm.expectRevert(bytes(Errors.INSUFFICIENT_LIQUIDITY)); + vm.expectRevert(bytes(ErrorsLib.INSUFFICIENT_LIQUIDITY)); blue.withdraw(market, sharesWithdrawn, address(this), receiver); return; } @@ -567,7 +567,7 @@ contract BlueTest is blue.borrow(market, amountBorrowed, BORROWER, BORROWER); } else { vm.prank(BORROWER); - vm.expectRevert(bytes(Errors.INSUFFICIENT_COLLATERAL)); + vm.expectRevert(bytes(ErrorsLib.INSUFFICIENT_COLLATERAL)); blue.borrow(market, amountBorrowed, BORROWER, BORROWER); } } @@ -580,8 +580,7 @@ contract BlueTest is uint256 borrowingPower = amountCollateral.mulWadDown(LLTV); uint256 amountBorrowed = borrowingPower.mulWadDown(0.8e18); uint256 toSeize = amountCollateral.mulWadDown(LLTV); - uint256 incentive = - FixedPointMathLib.WAD + ALPHA.mulWadDown(FixedPointMathLib.WAD.divWadDown(LLTV) - FixedPointMathLib.WAD); + uint256 incentive = WAD + ALPHA.mulWadDown(WAD.divWadDown(LLTV) - WAD); borrowableAsset.setBalance(address(this), amountLent); collateralAsset.setBalance(BORROWER, amountCollateral); @@ -624,8 +623,7 @@ contract BlueTest is uint256 borrowingPower = amountCollateral.mulWadDown(LLTV); uint256 amountBorrowed = borrowingPower.mulWadDown(0.8e18); uint256 toSeize = amountCollateral; - uint256 incentive = FixedPointMathLib.WAD - + ALPHA.mulWadDown(FixedPointMathLib.WAD.divWadDown(market.lltv) - FixedPointMathLib.WAD); + uint256 incentive = WAD + ALPHA.mulWadDown(WAD.divWadDown(market.lltv) - WAD); borrowableAsset.setBalance(address(this), amountLent); collateralAsset.setBalance(BORROWER, amountCollateral); @@ -677,12 +675,14 @@ contract BlueTest is assertApproxEqAbs(supplyBalance(address(this)), firstAmount, 100, "same balance first user"); assertEq( - blue.supplyShares(id, address(this)), firstAmount * SharesMath.VIRTUAL_SHARES, "expected shares first user" + blue.supplyShares(id, address(this)), + firstAmount * SharesMathLib.VIRTUAL_SHARES, + "expected shares first user" ); assertApproxEqAbs(supplyBalance(BORROWER), secondAmount, 100, "same balance second user"); assertApproxEqAbs( blue.supplyShares(id, BORROWER), - secondAmount * SharesMath.VIRTUAL_SHARES, + secondAmount * SharesMathLib.VIRTUAL_SHARES, 100, "expected shares second user" ); @@ -691,73 +691,73 @@ contract BlueTest is function testUnknownMarket(Market memory marketFuzz) public { vm.assume(neq(marketFuzz, market)); - vm.expectRevert(bytes(Errors.MARKET_NOT_CREATED)); + vm.expectRevert(bytes(ErrorsLib.MARKET_NOT_CREATED)); blue.supply(marketFuzz, 1, address(this), hex""); - vm.expectRevert(bytes(Errors.MARKET_NOT_CREATED)); + vm.expectRevert(bytes(ErrorsLib.MARKET_NOT_CREATED)); blue.withdraw(marketFuzz, 1, address(this), address(this)); - vm.expectRevert(bytes(Errors.MARKET_NOT_CREATED)); + vm.expectRevert(bytes(ErrorsLib.MARKET_NOT_CREATED)); blue.borrow(marketFuzz, 1, address(this), address(this)); - vm.expectRevert(bytes(Errors.MARKET_NOT_CREATED)); + vm.expectRevert(bytes(ErrorsLib.MARKET_NOT_CREATED)); blue.repay(marketFuzz, 1, address(this), hex""); - vm.expectRevert(bytes(Errors.MARKET_NOT_CREATED)); + vm.expectRevert(bytes(ErrorsLib.MARKET_NOT_CREATED)); blue.supplyCollateral(marketFuzz, 1, address(this), hex""); - vm.expectRevert(bytes(Errors.MARKET_NOT_CREATED)); + vm.expectRevert(bytes(ErrorsLib.MARKET_NOT_CREATED)); blue.withdrawCollateral(marketFuzz, 1, address(this), address(this)); - vm.expectRevert(bytes(Errors.MARKET_NOT_CREATED)); + vm.expectRevert(bytes(ErrorsLib.MARKET_NOT_CREATED)); blue.liquidate(marketFuzz, address(0), 1, hex""); } function testInputZero() public { - vm.expectRevert(bytes(Errors.ZERO_AMOUNT)); + vm.expectRevert(bytes(ErrorsLib.ZERO_AMOUNT)); blue.supply(market, 0, address(this), hex""); - vm.expectRevert(bytes(Errors.ZERO_SHARES)); + vm.expectRevert(bytes(ErrorsLib.ZERO_SHARES)); blue.withdraw(market, 0, address(this), address(this)); - vm.expectRevert(bytes(Errors.ZERO_AMOUNT)); + vm.expectRevert(bytes(ErrorsLib.ZERO_AMOUNT)); blue.borrow(market, 0, address(this), address(this)); - vm.expectRevert(bytes(Errors.ZERO_SHARES)); + vm.expectRevert(bytes(ErrorsLib.ZERO_SHARES)); blue.repay(market, 0, address(this), hex""); - vm.expectRevert(bytes(Errors.ZERO_AMOUNT)); + vm.expectRevert(bytes(ErrorsLib.ZERO_AMOUNT)); blue.supplyCollateral(market, 0, address(this), hex""); - vm.expectRevert(bytes(Errors.ZERO_AMOUNT)); + vm.expectRevert(bytes(ErrorsLib.ZERO_AMOUNT)); blue.withdrawCollateral(market, 0, address(this), address(this)); - vm.expectRevert(bytes(Errors.ZERO_AMOUNT)); + vm.expectRevert(bytes(ErrorsLib.ZERO_AMOUNT)); blue.liquidate(market, address(0), 0, hex""); } function testZeroAddress() public { - vm.expectRevert(bytes(Errors.ZERO_ADDRESS)); + vm.expectRevert(bytes(ErrorsLib.ZERO_ADDRESS)); blue.supply(market, 1, address(0), hex""); - vm.expectRevert(bytes(Errors.ZERO_ADDRESS)); + vm.expectRevert(bytes(ErrorsLib.ZERO_ADDRESS)); blue.withdraw(market, 1, address(this), address(0)); - vm.expectRevert(bytes(Errors.ZERO_ADDRESS)); + vm.expectRevert(bytes(ErrorsLib.ZERO_ADDRESS)); blue.borrow(market, 1, address(this), address(0)); - vm.expectRevert(bytes(Errors.ZERO_ADDRESS)); + vm.expectRevert(bytes(ErrorsLib.ZERO_ADDRESS)); blue.repay(market, 1, address(0), hex""); - vm.expectRevert(bytes(Errors.ZERO_ADDRESS)); + vm.expectRevert(bytes(ErrorsLib.ZERO_ADDRESS)); blue.supplyCollateral(market, 1, address(0), hex""); - vm.expectRevert(bytes(Errors.ZERO_ADDRESS)); + vm.expectRevert(bytes(ErrorsLib.ZERO_ADDRESS)); blue.withdrawCollateral(market, 1, address(this), address(0)); } function testEmptyMarket(uint256 amount) public { - amount = bound(amount, 1, type(uint256).max / SharesMath.VIRTUAL_SHARES); + amount = bound(amount, 1, type(uint256).max / SharesMathLib.VIRTUAL_SHARES); vm.expectRevert(stdError.arithmeticError); blue.withdraw(market, amount, address(this), address(this)); @@ -779,11 +779,11 @@ contract BlueTest is vm.startPrank(attacker); - vm.expectRevert(bytes(Errors.UNAUTHORIZED)); + vm.expectRevert(bytes(ErrorsLib.UNAUTHORIZED)); blue.withdraw(market, 1, address(this), address(this)); - vm.expectRevert(bytes(Errors.UNAUTHORIZED)); + vm.expectRevert(bytes(ErrorsLib.UNAUTHORIZED)); blue.withdrawCollateral(market, 1, address(this), address(this)); - vm.expectRevert(bytes(Errors.UNAUTHORIZED)); + vm.expectRevert(bytes(ErrorsLib.UNAUTHORIZED)); blue.borrow(market, 1, address(this), address(this)); vm.stopPrank(); diff --git a/test/forge/SharesMath.t.sol b/test/forge/SharesMathLib.t.sol similarity index 77% rename from test/forge/SharesMath.t.sol rename to test/forge/SharesMathLib.t.sol index 5165bab90..42b678bd7 100644 --- a/test/forge/SharesMath.t.sol +++ b/test/forge/SharesMathLib.t.sol @@ -4,15 +4,15 @@ pragma solidity ^0.8.0; import "forge-std/Test.sol"; import "forge-std/console2.sol"; -import {SharesMath} from "src/libraries/SharesMath.sol"; +import {SharesMathLib} from "src/libraries/SharesMathLib.sol"; -contract SharesMathTest is Test { - using SharesMath for uint256; +contract SharesMathLibTest is Test { + using SharesMathLib for uint256; function testToSupplyShares(uint256 amount, uint256 supplyShares, uint256 totalSupply, uint256 totalSupplyShares) public { - totalSupplyShares = bound(totalSupplyShares, SharesMath.VIRTUAL_SHARES, type(uint128).max); + totalSupplyShares = bound(totalSupplyShares, SharesMathLib.VIRTUAL_SHARES, type(uint128).max); totalSupply = bound(totalSupply, 0, totalSupplyShares); supplyShares = bound(supplyShares, 0, totalSupplyShares); @@ -27,7 +27,7 @@ contract SharesMathTest is Test { function testToBorrowShares(uint256 amount, uint256 borrowShares, uint256 totalBorrow, uint256 totalBorrowShares) public { - totalBorrowShares = bound(totalBorrowShares, SharesMath.VIRTUAL_SHARES, type(uint128).max); + totalBorrowShares = bound(totalBorrowShares, SharesMathLib.VIRTUAL_SHARES, type(uint128).max); totalBorrow = bound(totalBorrow, 0, totalBorrowShares); borrowShares = bound(borrowShares, 0, totalBorrowShares); From 55e5dcd1616f74228e0e00fe0b697f41c8b3e2db Mon Sep 17 00:00:00 2001 From: MathisGD Date: Tue, 8 Aug 2023 18:09:16 +0200 Subject: [PATCH 2/5] refactor: put libs constant as internal --- src/libraries/FixedPointMathLib.sol | 2 +- test/forge/Blue.t.sol | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libraries/FixedPointMathLib.sol b/src/libraries/FixedPointMathLib.sol index 63a7bb0f1..d2fca419c 100644 --- a/src/libraries/FixedPointMathLib.sol +++ b/src/libraries/FixedPointMathLib.sol @@ -7,7 +7,7 @@ uint256 constant WAD = 1e18; /// @dev Greatly inspired by Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/FixedPointMathLib.sol) /// and by USM (https://github.com/usmfum/USM/blob/master/contracts/WadMath.sol) library FixedPointMathLib { - uint256 private constant MAX_UINT256 = 2 ** 256 - 1; + uint256 internal constant MAX_UINT256 = 2 ** 256 - 1; /// @dev (x * y) / WAD rounded down. function mulWadDown(uint256 x, uint256 y) internal pure returns (uint256) { diff --git a/test/forge/Blue.t.sol b/test/forge/Blue.t.sol index 269f6cbbf..2f9e9c18a 100644 --- a/test/forge/Blue.t.sol +++ b/test/forge/Blue.t.sol @@ -43,8 +43,8 @@ contract BlueTest is Oracle private borrowableOracle; Oracle private collateralOracle; Irm private irm; - Market public market; - Id public id; + Market private market; + Id private id; function setUp() public { // Create Blue. From 492b25ca769f4d2d7bfd9ac7d89f1540f0a903f4 Mon Sep 17 00:00:00 2001 From: MathisGD Date: Thu, 10 Aug 2023 10:23:26 +0200 Subject: [PATCH 3/5] style: harmonize math functions naming --- src/Blue.sol | 10 ++++---- src/libraries/FixedPointMathLib.sol | 12 ++++----- src/mocks/IrmMock.sol | 2 +- test/forge/Blue.t.sol | 40 ++++++++++++++--------------- test/forge/Math.t.sol | 4 +-- 5 files changed, 34 insertions(+), 34 deletions(-) diff --git a/src/Blue.sol b/src/Blue.sol index 0d15048ce..b7a6f4fdd 100644 --- a/src/Blue.sol +++ b/src/Blue.sol @@ -287,8 +287,8 @@ contract Blue is IBlue { require(!_isHealthy(market, id, borrower, collateralPrice, priceScale), ErrorsLib.HEALTHY_POSITION); // The liquidation incentive is 1 + ALPHA * (1 / LLTV - 1). - uint256 incentive = WAD + ALPHA.mulWadDown(WAD.divWadDown(market.lltv) - WAD); - uint256 repaid = seized.mulDivUp(collateralPrice, priceScale).divWadUp(incentive); + uint256 incentive = WAD + ALPHA.wMulDown(WAD.wDivDown(market.lltv) - WAD); + uint256 repaid = seized.mulDivUp(collateralPrice, priceScale).wDivUp(incentive); uint256 repaidShares = repaid.toSharesDown(totalBorrow[id], totalBorrowShares[id]); borrowShares[id][borrower] -= repaidShares; @@ -377,13 +377,13 @@ contract Blue is IBlue { if (marketTotalBorrow != 0) { uint256 borrowRate = IIrm(market.irm).borrowRate(market); - uint256 accruedInterests = marketTotalBorrow.mulWadDown(borrowRate.wTaylorCompounded(elapsed)); + uint256 accruedInterests = marketTotalBorrow.wMulDown(borrowRate.wTaylorCompounded(elapsed)); totalBorrow[id] = marketTotalBorrow + accruedInterests; totalSupply[id] += accruedInterests; uint256 feeShares; if (fee[id] != 0) { - uint256 feeAmount = accruedInterests.mulWadDown(fee[id]); + uint256 feeAmount = accruedInterests.wMulDown(fee[id]); // The fee amount is subtracted from the total supply in this calculation to compensate for the fact that total supply is already updated. feeShares = feeAmount.mulDivDown(totalSupplyShares[id], totalSupply[id] - feeAmount); supplyShares[id][feeRecipient] += feeShares; @@ -412,7 +412,7 @@ contract Blue is IBlue { returns (bool) { uint256 borrowed = borrowShares[id][user].toAssetsUp(totalBorrow[id], totalBorrowShares[id]); - uint256 maxBorrow = collateral[id][user].mulDivDown(collateralPrice, priceScale).mulWadDown(market.lltv); + uint256 maxBorrow = collateral[id][user].mulDivDown(collateralPrice, priceScale).wMulDown(market.lltv); return maxBorrow >= borrowed; } diff --git a/src/libraries/FixedPointMathLib.sol b/src/libraries/FixedPointMathLib.sol index 9131b0d97..ccb713f77 100644 --- a/src/libraries/FixedPointMathLib.sol +++ b/src/libraries/FixedPointMathLib.sol @@ -10,22 +10,22 @@ library FixedPointMathLib { uint256 internal constant MAX_UINT256 = 2 ** 256 - 1; /// @dev (x * y) / WAD rounded down. - function mulWadDown(uint256 x, uint256 y) internal pure returns (uint256) { + function wMulDown(uint256 x, uint256 y) internal pure returns (uint256) { return mulDivDown(x, y, WAD); } /// @dev (x * y) / WAD rounded up. - function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256) { + function wMulUp(uint256 x, uint256 y) internal pure returns (uint256) { return mulDivUp(x, y, WAD); } /// @dev (x * WAD) / y rounded down. - function divWadDown(uint256 x, uint256 y) internal pure returns (uint256) { + function wDivDown(uint256 x, uint256 y) internal pure returns (uint256) { return mulDivDown(x, WAD, y); } /// @dev (x * WAD) / y rounded up. - function divWadUp(uint256 x, uint256 y) internal pure returns (uint256) { + function wDivUp(uint256 x, uint256 y) internal pure returns (uint256) { return mulDivUp(x, WAD, y); } @@ -58,8 +58,8 @@ library FixedPointMathLib { /// to approximate a compound interest rate: (1 + x)^n - 1. function wTaylorCompounded(uint256 x, uint256 n) internal pure returns (uint256) { uint256 firstTerm = x * n; - uint256 secondTerm = mulWadDown(firstTerm, x * zeroFloorSub(n, 1)) / 2; - uint256 thirdTerm = mulWadDown(secondTerm, x * zeroFloorSub(n, 2)) / 3; + uint256 secondTerm = wMulDown(firstTerm, x * zeroFloorSub(n, 1)) / 2; + uint256 thirdTerm = wMulDown(secondTerm, x * zeroFloorSub(n, 2)) / 3; return firstTerm + secondTerm + thirdTerm; } diff --git a/src/mocks/IrmMock.sol b/src/mocks/IrmMock.sol index f0558d2ad..9ab5a07f3 100644 --- a/src/mocks/IrmMock.sol +++ b/src/mocks/IrmMock.sol @@ -19,7 +19,7 @@ contract IrmMock is IIrm { 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).wDivDown(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. diff --git a/test/forge/Blue.t.sol b/test/forge/Blue.t.sol index 73f5b8fe8..69660b755 100644 --- a/test/forge/Blue.t.sol +++ b/test/forge/Blue.t.sol @@ -99,7 +99,7 @@ contract BlueTest is uint256 totalShares = blue.totalSupplyShares(id); uint256 totalSupply = blue.totalSupply(id); - return supplyShares.divWadDown(totalShares).mulWadDown(totalSupply); + return supplyShares.wDivDown(totalShares).wMulDown(totalSupply); } function borrowBalance(address user) internal view returns (uint256) { @@ -108,7 +108,7 @@ contract BlueTest is uint256 totalShares = blue.totalBorrowShares(id); uint256 totalBorrow = blue.totalBorrow(id); - return borrowerShares.divWadUp(totalShares).mulWadUp(totalBorrow); + return borrowerShares.wDivUp(totalShares).wMulUp(totalBorrow); } // Invariants @@ -276,7 +276,7 @@ contract BlueTest is borrowableAsset.setBalance(address(this), amountLent); blue.supply(market, amountLent, address(this), hex""); - uint256 collateralAmount = amountBorrowed.divWadUp(LLTV); + uint256 collateralAmount = amountBorrowed.wDivUp(LLTV); collateralAsset.setBalance(address(this), collateralAmount); blue.supplyCollateral(market, collateralAmount, BORROWER, hex""); @@ -297,7 +297,7 @@ contract BlueTest is vm.assume(totalSupplyAfter > totalSupplyBefore); uint256 accrued = totalSupplyAfter - totalSupplyBefore; - uint256 expectedFee = accrued.mulWadDown(fee); + uint256 expectedFee = accrued.wMulDown(fee); uint256 expectedFeeShares = expectedFee.mulDivDown(totalSupplySharesBefore, totalSupplyAfter - expectedFee); assertEq(blue.supplyShares(id, recipient), expectedFeeShares); @@ -334,7 +334,7 @@ contract BlueTest is borrowableAsset.setBalance(address(this), amountLent); blue.supply(market, amountLent, address(this), hex""); - uint256 collateralAmount = amountBorrowed.divWadUp(LLTV); + uint256 collateralAmount = amountBorrowed.wDivUp(LLTV); collateralAsset.setBalance(address(this), collateralAmount); blue.supplyCollateral(market, collateralAmount, BORROWER, hex""); @@ -378,7 +378,7 @@ contract BlueTest is _testWithdrawCommon(amountLent); amountBorrowed = bound(amountBorrowed, 1, blue.totalSupply(id)); - uint256 collateralAmount = amountBorrowed.divWadUp(LLTV); + uint256 collateralAmount = amountBorrowed.wDivUp(LLTV); collateralAsset.setBalance(address(this), collateralAmount); blue.supplyCollateral(market, collateralAmount, BORROWER, hex""); @@ -443,7 +443,7 @@ contract BlueTest is borrowableAsset.setBalance(address(this), 2 ** 66); blue.supply(market, amountBorrowed, address(this), hex""); - uint256 collateralAmount = amountBorrowed.divWadUp(LLTV); + uint256 collateralAmount = amountBorrowed.wDivUp(LLTV); collateralAsset.setBalance(address(this), collateralAmount); blue.supplyCollateral(market, collateralAmount, borrower, hex""); @@ -566,7 +566,7 @@ contract BlueTest is vm.prank(BORROWER); blue.supplyCollateral(market, amountCollateral, BORROWER, hex""); - uint256 maxBorrow = amountCollateral.mulWadDown(collateralPrice).mulWadDown(LLTV); + uint256 maxBorrow = amountCollateral.wMulDown(collateralPrice).wMulDown(LLTV); vm.prank(BORROWER); if (maxBorrow < amountBorrowed) vm.expectRevert(bytes(ErrorsLib.INSUFFICIENT_COLLATERAL)); @@ -578,10 +578,10 @@ contract BlueTest is amountLent = bound(amountLent, 1000, 2 ** 64); uint256 amountCollateral = amountLent; - uint256 borrowingPower = amountCollateral.mulWadDown(LLTV); - uint256 amountBorrowed = borrowingPower.mulWadDown(0.8e18); - uint256 toSeize = amountCollateral.mulWadDown(LLTV); - uint256 incentive = WAD + ALPHA.mulWadDown(WAD.divWadDown(LLTV) - WAD); + uint256 borrowingPower = amountCollateral.wMulDown(LLTV); + uint256 amountBorrowed = borrowingPower.wMulDown(0.8e18); + uint256 toSeize = amountCollateral.wMulDown(LLTV); + uint256 incentive = WAD + ALPHA.wMulDown(WAD.wDivDown(LLTV) - WAD); borrowableAsset.setBalance(address(this), amountLent); collateralAsset.setBalance(BORROWER, amountCollateral); @@ -608,7 +608,7 @@ contract BlueTest is uint256 liquidatorNetWorthAfter = netWorth(LIQUIDATOR); (uint256 collateralPrice, uint256 priceScale) = IOracle(market.oracle).price(); - uint256 expectedRepaid = toSeize.mulDivUp(collateralPrice, priceScale).divWadUp(incentive); + uint256 expectedRepaid = toSeize.mulDivUp(collateralPrice, priceScale).wDivUp(incentive); uint256 expectedNetWorthAfter = liquidatorNetWorthBefore + toSeize.mulDivDown(collateralPrice, priceScale) - expectedRepaid; assertEq(liquidatorNetWorthAfter, expectedNetWorthAfter, "LIQUIDATOR net worth"); @@ -621,10 +621,10 @@ contract BlueTest is amountLent = bound(amountLent, 1000, 2 ** 64); uint256 amountCollateral = amountLent; - uint256 borrowingPower = amountCollateral.mulWadDown(LLTV); - uint256 amountBorrowed = borrowingPower.mulWadDown(0.8e18); + uint256 borrowingPower = amountCollateral.wMulDown(LLTV); + uint256 amountBorrowed = borrowingPower.wMulDown(0.8e18); uint256 toSeize = amountCollateral; - uint256 incentive = WAD + ALPHA.mulWadDown(WAD.divWadDown(market.lltv) - WAD); + uint256 incentive = WAD + ALPHA.wMulDown(WAD.wDivDown(market.lltv) - WAD); borrowableAsset.setBalance(address(this), amountLent); collateralAsset.setBalance(BORROWER, amountCollateral); @@ -651,7 +651,7 @@ contract BlueTest is uint256 liquidatorNetWorthAfter = netWorth(LIQUIDATOR); (uint256 collateralPrice, uint256 priceScale) = IOracle(market.oracle).price(); - uint256 expectedRepaid = toSeize.mulDivUp(collateralPrice, priceScale).divWadUp(incentive); + uint256 expectedRepaid = toSeize.mulDivUp(collateralPrice, priceScale).wDivUp(incentive); uint256 expectedNetWorthAfter = liquidatorNetWorthBefore + toSeize.mulDivDown(collateralPrice, priceScale) - expectedRepaid; assertEq(liquidatorNetWorthAfter, expectedNetWorthAfter, "LIQUIDATOR net worth"); @@ -891,7 +891,7 @@ contract BlueTest is borrowableAsset.setBalance(address(this), amount); blue.supply(market, amount, address(this), hex""); - uint256 collateralAmount = amount.divWadUp(LLTV); + uint256 collateralAmount = amount.wDivUp(LLTV); collateralAsset.setBalance(address(this), collateralAmount); blue.supplyCollateral(market, collateralAmount, address(this), hex""); blue.borrow(market, amount, address(this), address(this)); @@ -909,7 +909,7 @@ contract BlueTest is borrowableAsset.setBalance(address(this), amount); blue.supply(market, amount, address(this), hex""); - uint256 collateralAmount = amount.divWadUp(LLTV); + uint256 collateralAmount = amount.wDivUp(LLTV); collateralAsset.setBalance(address(this), collateralAmount); blue.supplyCollateral(market, collateralAmount, address(this), hex""); blue.borrow(market, amount, address(this), address(this)); @@ -926,7 +926,7 @@ contract BlueTest is function testFlashActions(uint256 amount) public { amount = bound(amount, 10, 2 ** 64); oracle.setPrice(1e18); - uint256 toBorrow = amount.mulWadDown(LLTV); + uint256 toBorrow = amount.wMulDown(LLTV); borrowableAsset.setBalance(address(this), 2 * toBorrow); blue.supply(market, toBorrow, address(this), hex""); diff --git a/test/forge/Math.t.sol b/test/forge/Math.t.sol index c8c334eaf..76e6c4746 100644 --- a/test/forge/Math.t.sol +++ b/test/forge/Math.t.sol @@ -22,8 +22,8 @@ contract MathTest is Test { function wPow(uint256 x, uint256 n) private pure returns (uint256 z) { z = WAD; for (; n != 0; n /= 2) { - z = n % 2 != 0 ? z.mulWadUp(x) : z; - x = x.mulWadUp(x); + z = n % 2 != 0 ? z.wMulUp(x) : z; + x = x.wMulUp(x); } } } From baf2ea1008cb86677424fc8bbe46111880fe6b7c Mon Sep 17 00:00:00 2001 From: MathisGD Date: Thu, 10 Aug 2023 11:23:59 +0200 Subject: [PATCH 4/5] refactor: move errors to IBlue --- src/Blue.sol | 85 +++++++++++++++++-------------------- src/interfaces/IBlue.sol | 32 ++++++++++++++ src/libraries/ErrorsLib.sol | 36 ---------------- test/forge/Blue.t.sol | 72 +++++++++++++++---------------- 4 files changed, 107 insertions(+), 118 deletions(-) delete mode 100644 src/libraries/ErrorsLib.sol diff --git a/src/Blue.sol b/src/Blue.sol index b7a6f4fdd..4279b0783 100644 --- a/src/Blue.sol +++ b/src/Blue.sol @@ -1,19 +1,12 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.21; -import { - IBlueLiquidateCallback, - IBlueRepayCallback, - IBlueSupplyCallback, - IBlueSupplyCollateralCallback, - IBlueFlashLoanCallback -} from "./interfaces/IBlueCallbacks.sol"; +import "./interfaces/IBlue.sol"; +import "./interfaces/IBlueCallbacks.sol"; import {IIrm} from "./interfaces/IIrm.sol"; import {IERC20} from "./interfaces/IERC20.sol"; import {IOracle} from "./interfaces/IOracle.sol"; -import {Id, Market, Signature, IBlue} from "./interfaces/IBlue.sol"; -import {ErrorsLib} from "./libraries/ErrorsLib.sol"; import {MarketLib} from "./libraries/MarketLib.sol"; import {SharesMathLib} from "./libraries/SharesMathLib.sol"; import {SafeTransferLib} from "./libraries/SafeTransferLib.sol"; @@ -83,7 +76,7 @@ contract Blue is IBlue { // Modifiers. modifier onlyOwner() { - require(msg.sender == owner, ErrorsLib.NOT_OWNER); + require(msg.sender == owner, NOT_OWNER); _; } @@ -102,7 +95,7 @@ contract Blue is IBlue { } function enableLltv(uint256 lltv) external onlyOwner { - require(lltv < WAD, ErrorsLib.LLTV_TOO_HIGH); + require(lltv < WAD, LLTV_TOO_HIGH); isLltvEnabled[lltv] = true; emit EnableLltv(lltv); @@ -111,8 +104,8 @@ contract Blue is IBlue { /// @notice It is the owner's responsibility to ensure a fee recipient is set before setting a non-zero fee. function setFee(Market memory market, uint256 newFee) external onlyOwner { Id id = market.id(); - require(lastUpdate[id] != 0, ErrorsLib.MARKET_NOT_CREATED); - require(newFee <= MAX_FEE, ErrorsLib.MAX_FEE_EXCEEDED); + require(lastUpdate[id] != 0, MARKET_NOT_CREATED); + require(newFee <= MAX_FEE, MAX_FEE_EXCEEDED); // Accrue interests using the previous fee set before changing it. _accrueInterests(market, id); @@ -132,9 +125,9 @@ contract Blue is IBlue { function createMarket(Market memory market) external { Id id = market.id(); - require(isIrmEnabled[market.irm], ErrorsLib.IRM_NOT_ENABLED); - require(isLltvEnabled[market.lltv], ErrorsLib.LLTV_NOT_ENABLED); - require(lastUpdate[id] == 0, ErrorsLib.MARKET_CREATED); + require(isIrmEnabled[market.irm], IRM_NOT_ENABLED); + require(isLltvEnabled[market.lltv], LLTV_NOT_ENABLED); + require(lastUpdate[id] == 0, MARKET_CREATED); lastUpdate[id] = block.timestamp; @@ -145,9 +138,9 @@ contract Blue is IBlue { function supply(Market memory market, uint256 amount, address onBehalf, bytes calldata data) external { Id id = market.id(); - require(lastUpdate[id] != 0, ErrorsLib.MARKET_NOT_CREATED); - require(amount != 0, ErrorsLib.ZERO_AMOUNT); - require(onBehalf != address(0), ErrorsLib.ZERO_ADDRESS); + require(lastUpdate[id] != 0, MARKET_NOT_CREATED); + require(amount != 0, ZERO_AMOUNT); + require(onBehalf != address(0), ZERO_ADDRESS); _accrueInterests(market, id); @@ -166,11 +159,11 @@ contract Blue is IBlue { function withdraw(Market memory market, uint256 shares, address onBehalf, address receiver) external { Id id = market.id(); - require(lastUpdate[id] != 0, ErrorsLib.MARKET_NOT_CREATED); - require(shares != 0, ErrorsLib.ZERO_SHARES); + require(lastUpdate[id] != 0, MARKET_NOT_CREATED); + require(shares != 0, ZERO_SHARES); // No need to verify that onBehalf != address(0) thanks to the authorization check. - require(receiver != address(0), ErrorsLib.ZERO_ADDRESS); - require(_isSenderAuthorized(onBehalf), ErrorsLib.UNAUTHORIZED); + require(receiver != address(0), ZERO_ADDRESS); + require(_isSenderAuthorized(onBehalf), UNAUTHORIZED); _accrueInterests(market, id); @@ -182,7 +175,7 @@ contract Blue is IBlue { emit Withdraw(id, msg.sender, onBehalf, receiver, amount, shares); - require(totalBorrow[id] <= totalSupply[id], ErrorsLib.INSUFFICIENT_LIQUIDITY); + require(totalBorrow[id] <= totalSupply[id], INSUFFICIENT_LIQUIDITY); IERC20(market.borrowableAsset).safeTransfer(receiver, amount); } @@ -191,11 +184,11 @@ contract Blue is IBlue { function borrow(Market memory market, uint256 amount, address onBehalf, address receiver) external { Id id = market.id(); - require(lastUpdate[id] != 0, ErrorsLib.MARKET_NOT_CREATED); - require(amount != 0, ErrorsLib.ZERO_AMOUNT); + require(lastUpdate[id] != 0, MARKET_NOT_CREATED); + require(amount != 0, ZERO_AMOUNT); // No need to verify that onBehalf != address(0) thanks to the authorization check. - require(receiver != address(0), ErrorsLib.ZERO_ADDRESS); - require(_isSenderAuthorized(onBehalf), ErrorsLib.UNAUTHORIZED); + require(receiver != address(0), ZERO_ADDRESS); + require(_isSenderAuthorized(onBehalf), UNAUTHORIZED); _accrueInterests(market, id); @@ -207,17 +200,17 @@ contract Blue is IBlue { emit Borrow(id, msg.sender, onBehalf, receiver, amount, shares); - require(_isHealthy(market, id, onBehalf), ErrorsLib.INSUFFICIENT_COLLATERAL); - require(totalBorrow[id] <= totalSupply[id], ErrorsLib.INSUFFICIENT_LIQUIDITY); + require(_isHealthy(market, id, onBehalf), INSUFFICIENT_COLLATERAL); + require(totalBorrow[id] <= totalSupply[id], INSUFFICIENT_LIQUIDITY); IERC20(market.borrowableAsset).safeTransfer(receiver, amount); } function repay(Market memory market, uint256 shares, address onBehalf, bytes calldata data) external { Id id = market.id(); - require(lastUpdate[id] != 0, ErrorsLib.MARKET_NOT_CREATED); - require(shares != 0, ErrorsLib.ZERO_SHARES); - require(onBehalf != address(0), ErrorsLib.ZERO_ADDRESS); + require(lastUpdate[id] != 0, MARKET_NOT_CREATED); + require(shares != 0, ZERO_SHARES); + require(onBehalf != address(0), ZERO_ADDRESS); _accrueInterests(market, id); @@ -239,9 +232,9 @@ contract Blue is IBlue { /// @dev Don't accrue interests because it's not required and it saves gas. function supplyCollateral(Market memory market, uint256 amount, address onBehalf, bytes calldata data) external { Id id = market.id(); - require(lastUpdate[id] != 0, ErrorsLib.MARKET_NOT_CREATED); - require(amount != 0, ErrorsLib.ZERO_AMOUNT); - require(onBehalf != address(0), ErrorsLib.ZERO_ADDRESS); + require(lastUpdate[id] != 0, MARKET_NOT_CREATED); + require(amount != 0, ZERO_AMOUNT); + require(onBehalf != address(0), ZERO_ADDRESS); // Don't accrue interests because it's not required and it saves gas. @@ -256,11 +249,11 @@ contract Blue is IBlue { function withdrawCollateral(Market memory market, uint256 amount, address onBehalf, address receiver) external { Id id = market.id(); - require(lastUpdate[id] != 0, ErrorsLib.MARKET_NOT_CREATED); - require(amount != 0, ErrorsLib.ZERO_AMOUNT); + require(lastUpdate[id] != 0, MARKET_NOT_CREATED); + require(amount != 0, ZERO_AMOUNT); // No need to verify that onBehalf != address(0) thanks to the authorization check. - require(receiver != address(0), ErrorsLib.ZERO_ADDRESS); - require(_isSenderAuthorized(onBehalf), ErrorsLib.UNAUTHORIZED); + require(receiver != address(0), ZERO_ADDRESS); + require(_isSenderAuthorized(onBehalf), UNAUTHORIZED); _accrueInterests(market, id); @@ -268,7 +261,7 @@ contract Blue is IBlue { emit WithdrawCollateral(id, msg.sender, onBehalf, receiver, amount); - require(_isHealthy(market, id, onBehalf), ErrorsLib.INSUFFICIENT_COLLATERAL); + require(_isHealthy(market, id, onBehalf), INSUFFICIENT_COLLATERAL); IERC20(market.collateralAsset).safeTransfer(receiver, amount); } @@ -277,14 +270,14 @@ contract Blue is IBlue { function liquidate(Market memory market, address borrower, uint256 seized, bytes calldata data) external { Id id = market.id(); - require(lastUpdate[id] != 0, ErrorsLib.MARKET_NOT_CREATED); - require(seized != 0, ErrorsLib.ZERO_AMOUNT); + require(lastUpdate[id] != 0, MARKET_NOT_CREATED); + require(seized != 0, ZERO_AMOUNT); _accrueInterests(market, id); (uint256 collateralPrice, uint256 priceScale) = IOracle(market.oracle).price(); - require(!_isHealthy(market, id, borrower, collateralPrice, priceScale), ErrorsLib.HEALTHY_POSITION); + require(!_isHealthy(market, id, borrower, collateralPrice, priceScale), HEALTHY_POSITION); // The liquidation incentive is 1 + ALPHA * (1 / LLTV - 1). uint256 incentive = WAD + ALPHA.wMulDown(WAD.wDivDown(market.lltv) - WAD); @@ -345,7 +338,7 @@ contract Blue is IBlue { uint256 deadline, Signature calldata signature ) external { - require(block.timestamp < deadline, ErrorsLib.SIGNATURE_EXPIRED); + require(block.timestamp < deadline, SIGNATURE_EXPIRED); uint256 usedNonce = nonce[authorizer]++; bytes32 hashStruct = @@ -353,7 +346,7 @@ contract Blue is IBlue { bytes32 digest = keccak256(abi.encodePacked("\x19\x01", DOMAIN_SEPARATOR, hashStruct)); address signatory = ecrecover(digest, signature.v, signature.r, signature.s); - require(signatory != address(0) && authorizer == signatory, ErrorsLib.INVALID_SIGNATURE); + require(signatory != address(0) && authorizer == signatory, INVALID_SIGNATURE); emit IncrementNonce(msg.sender, authorizer, usedNonce); diff --git a/src/interfaces/IBlue.sol b/src/interfaces/IBlue.sol index c553e932e..39cba1a05 100644 --- a/src/interfaces/IBlue.sol +++ b/src/interfaces/IBlue.sol @@ -20,6 +20,38 @@ struct Signature { bytes32 s; } +string constant NOT_OWNER = "not owner"; + +string constant LLTV_TOO_HIGH = "LLTV too high"; + +string constant MAX_FEE_EXCEEDED = "MAX_FEE exceeded"; + +string constant IRM_NOT_ENABLED = "IRM not enabled"; + +string constant LLTV_NOT_ENABLED = "LLTV not enabled"; + +string constant MARKET_CREATED = "market created"; + +string constant MARKET_NOT_CREATED = "market not created"; + +string constant ZERO_AMOUNT = "zero amount"; + +string constant ZERO_SHARES = "zero shares"; + +string constant ZERO_ADDRESS = "zero address"; + +string constant UNAUTHORIZED = "unauthorized"; + +string constant INSUFFICIENT_COLLATERAL = "insufficient collateral"; + +string constant INSUFFICIENT_LIQUIDITY = "insufficient liquidity"; + +string constant HEALTHY_POSITION = "position is healthy"; + +string constant INVALID_SIGNATURE = "invalid signature"; + +string constant SIGNATURE_EXPIRED = "signature expired"; + interface IBlue is IFlashLender { event SupplyCollateral(Id indexed id, address indexed caller, address indexed onBehalf, uint256 amount); event WithdrawCollateral( diff --git a/src/libraries/ErrorsLib.sol b/src/libraries/ErrorsLib.sol deleted file mode 100644 index 08c5513ad..000000000 --- a/src/libraries/ErrorsLib.sol +++ /dev/null @@ -1,36 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.0; - -library ErrorsLib { - string internal constant NOT_OWNER = "not owner"; - - string internal constant LLTV_TOO_HIGH = "LLTV too high"; - - string internal constant MAX_FEE_EXCEEDED = "MAX_FEE exceeded"; - - string internal constant IRM_NOT_ENABLED = "IRM not enabled"; - - string internal constant LLTV_NOT_ENABLED = "LLTV not enabled"; - - string internal constant MARKET_CREATED = "market created"; - - string internal constant MARKET_NOT_CREATED = "market not created"; - - string internal constant ZERO_AMOUNT = "zero amount"; - - string internal constant ZERO_SHARES = "zero shares"; - - string internal constant ZERO_ADDRESS = "zero address"; - - string internal constant UNAUTHORIZED = "unauthorized"; - - string internal constant INSUFFICIENT_COLLATERAL = "insufficient collateral"; - - string internal constant INSUFFICIENT_LIQUIDITY = "insufficient liquidity"; - - string internal constant HEALTHY_POSITION = "position is healthy"; - - string internal constant INVALID_SIGNATURE = "invalid signature"; - - string internal constant SIGNATURE_EXPIRED = "signature expired"; -} diff --git a/test/forge/Blue.t.sol b/test/forge/Blue.t.sol index 69660b755..c1eface1e 100644 --- a/test/forge/Blue.t.sol +++ b/test/forge/Blue.t.sol @@ -151,7 +151,7 @@ contract BlueTest is Blue blue2 = new Blue(OWNER); vm.prank(attacker); - vm.expectRevert(bytes(ErrorsLib.NOT_OWNER)); + vm.expectRevert(bytes(NOT_OWNER)); blue2.setOwner(newOwner); } @@ -159,7 +159,7 @@ contract BlueTest is vm.assume(attacker != blue.owner()); vm.prank(attacker); - vm.expectRevert(bytes(ErrorsLib.NOT_OWNER)); + vm.expectRevert(bytes(NOT_OWNER)); blue.enableIrm(newIrm); } @@ -183,7 +183,7 @@ contract BlueTest is vm.assume(marketFuzz.irm != address(irm)); vm.prank(OWNER); - vm.expectRevert(bytes(ErrorsLib.IRM_NOT_ENABLED)); + vm.expectRevert(bytes(IRM_NOT_ENABLED)); blue.createMarket(marketFuzz); } @@ -191,7 +191,7 @@ contract BlueTest is vm.assume(attacker != OWNER); vm.prank(attacker); - vm.expectRevert(bytes(ErrorsLib.NOT_OWNER)); + vm.expectRevert(bytes(NOT_OWNER)); blue.enableLltv(newLltv); } @@ -208,7 +208,7 @@ contract BlueTest is newLltv = bound(newLltv, WAD, type(uint256).max); vm.prank(OWNER); - vm.expectRevert(bytes(ErrorsLib.LLTV_TOO_HIGH)); + vm.expectRevert(bytes(LLTV_TOO_HIGH)); blue.enableLltv(newLltv); } @@ -225,7 +225,7 @@ contract BlueTest is fee = bound(fee, MAX_FEE + 1, type(uint256).max); vm.prank(OWNER); - vm.expectRevert(bytes(ErrorsLib.MAX_FEE_EXCEEDED)); + vm.expectRevert(bytes(MAX_FEE_EXCEEDED)); blue.setFee(market, fee); } @@ -234,7 +234,7 @@ contract BlueTest is fee = bound(fee, 0, WAD); vm.prank(OWNER); - vm.expectRevert(bytes(ErrorsLib.MARKET_NOT_CREATED)); + vm.expectRevert(bytes(MARKET_NOT_CREATED)); blue.setFee(marketFuzz, fee); } @@ -242,7 +242,7 @@ contract BlueTest is vm.assume(caller != OWNER); fee = bound(fee, 0, WAD); - vm.expectRevert(bytes(ErrorsLib.NOT_OWNER)); + vm.expectRevert(bytes(NOT_OWNER)); blue.setFee(market, fee); } @@ -256,7 +256,7 @@ contract BlueTest is function testSetFeeRecipientShouldRevertIfNotOwner(address caller, address recipient) public { vm.assume(caller != OWNER); - vm.expectRevert(bytes(ErrorsLib.NOT_OWNER)); + vm.expectRevert(bytes(NOT_OWNER)); vm.prank(caller); blue.setFeeRecipient(recipient); } @@ -308,7 +308,7 @@ contract BlueTest is marketFuzz.irm = address(irm); vm.prank(OWNER); - vm.expectRevert(bytes(ErrorsLib.LLTV_NOT_ENABLED)); + vm.expectRevert(bytes(LLTV_NOT_ENABLED)); blue.createMarket(marketFuzz); } @@ -340,7 +340,7 @@ contract BlueTest is if (amountBorrowed > amountLent) { vm.prank(BORROWER); - vm.expectRevert(bytes(ErrorsLib.INSUFFICIENT_LIQUIDITY)); + vm.expectRevert(bytes(INSUFFICIENT_LIQUIDITY)); blue.borrow(market, amountBorrowed, BORROWER, receiver); return; } @@ -393,7 +393,7 @@ contract BlueTest is blue.withdraw(market, sharesWithdrawn, address(this), receiver); return; } else if (amountWithdrawn > totalSupplyBefore - amountBorrowed) { - vm.expectRevert(bytes(ErrorsLib.INSUFFICIENT_LIQUIDITY)); + vm.expectRevert(bytes(INSUFFICIENT_LIQUIDITY)); blue.withdraw(market, sharesWithdrawn, address(this), receiver); return; } @@ -569,7 +569,7 @@ contract BlueTest is uint256 maxBorrow = amountCollateral.wMulDown(collateralPrice).wMulDown(LLTV); vm.prank(BORROWER); - if (maxBorrow < amountBorrowed) vm.expectRevert(bytes(ErrorsLib.INSUFFICIENT_COLLATERAL)); + if (maxBorrow < amountBorrowed) vm.expectRevert(bytes(INSUFFICIENT_COLLATERAL)); blue.borrow(market, amountBorrowed, BORROWER, BORROWER); } @@ -692,68 +692,68 @@ contract BlueTest is function testUnknownMarket(Market memory marketFuzz) public { vm.assume(neq(marketFuzz, market)); - vm.expectRevert(bytes(ErrorsLib.MARKET_NOT_CREATED)); + vm.expectRevert(bytes(MARKET_NOT_CREATED)); blue.supply(marketFuzz, 1, address(this), hex""); - vm.expectRevert(bytes(ErrorsLib.MARKET_NOT_CREATED)); + vm.expectRevert(bytes(MARKET_NOT_CREATED)); blue.withdraw(marketFuzz, 1, address(this), address(this)); - vm.expectRevert(bytes(ErrorsLib.MARKET_NOT_CREATED)); + vm.expectRevert(bytes(MARKET_NOT_CREATED)); blue.borrow(marketFuzz, 1, address(this), address(this)); - vm.expectRevert(bytes(ErrorsLib.MARKET_NOT_CREATED)); + vm.expectRevert(bytes(MARKET_NOT_CREATED)); blue.repay(marketFuzz, 1, address(this), hex""); - vm.expectRevert(bytes(ErrorsLib.MARKET_NOT_CREATED)); + vm.expectRevert(bytes(MARKET_NOT_CREATED)); blue.supplyCollateral(marketFuzz, 1, address(this), hex""); - vm.expectRevert(bytes(ErrorsLib.MARKET_NOT_CREATED)); + vm.expectRevert(bytes(MARKET_NOT_CREATED)); blue.withdrawCollateral(marketFuzz, 1, address(this), address(this)); - vm.expectRevert(bytes(ErrorsLib.MARKET_NOT_CREATED)); + vm.expectRevert(bytes(MARKET_NOT_CREATED)); blue.liquidate(marketFuzz, address(0), 1, hex""); } function testInputZero() public { - vm.expectRevert(bytes(ErrorsLib.ZERO_AMOUNT)); + vm.expectRevert(bytes(ZERO_AMOUNT)); blue.supply(market, 0, address(this), hex""); - vm.expectRevert(bytes(ErrorsLib.ZERO_SHARES)); + vm.expectRevert(bytes(ZERO_SHARES)); blue.withdraw(market, 0, address(this), address(this)); - vm.expectRevert(bytes(ErrorsLib.ZERO_AMOUNT)); + vm.expectRevert(bytes(ZERO_AMOUNT)); blue.borrow(market, 0, address(this), address(this)); - vm.expectRevert(bytes(ErrorsLib.ZERO_SHARES)); + vm.expectRevert(bytes(ZERO_SHARES)); blue.repay(market, 0, address(this), hex""); - vm.expectRevert(bytes(ErrorsLib.ZERO_AMOUNT)); + vm.expectRevert(bytes(ZERO_AMOUNT)); blue.supplyCollateral(market, 0, address(this), hex""); - vm.expectRevert(bytes(ErrorsLib.ZERO_AMOUNT)); + vm.expectRevert(bytes(ZERO_AMOUNT)); blue.withdrawCollateral(market, 0, address(this), address(this)); - vm.expectRevert(bytes(ErrorsLib.ZERO_AMOUNT)); + vm.expectRevert(bytes(ZERO_AMOUNT)); blue.liquidate(market, address(0), 0, hex""); } function testZeroAddress() public { - vm.expectRevert(bytes(ErrorsLib.ZERO_ADDRESS)); + vm.expectRevert(bytes(ZERO_ADDRESS)); blue.supply(market, 1, address(0), hex""); - vm.expectRevert(bytes(ErrorsLib.ZERO_ADDRESS)); + vm.expectRevert(bytes(ZERO_ADDRESS)); blue.withdraw(market, 1, address(this), address(0)); - vm.expectRevert(bytes(ErrorsLib.ZERO_ADDRESS)); + vm.expectRevert(bytes(ZERO_ADDRESS)); blue.borrow(market, 1, address(this), address(0)); - vm.expectRevert(bytes(ErrorsLib.ZERO_ADDRESS)); + vm.expectRevert(bytes(ZERO_ADDRESS)); blue.repay(market, 1, address(0), hex""); - vm.expectRevert(bytes(ErrorsLib.ZERO_ADDRESS)); + vm.expectRevert(bytes(ZERO_ADDRESS)); blue.supplyCollateral(market, 1, address(0), hex""); - vm.expectRevert(bytes(ErrorsLib.ZERO_ADDRESS)); + vm.expectRevert(bytes(ZERO_ADDRESS)); blue.withdrawCollateral(market, 1, address(this), address(0)); } @@ -780,11 +780,11 @@ contract BlueTest is vm.startPrank(attacker); - vm.expectRevert(bytes(ErrorsLib.UNAUTHORIZED)); + vm.expectRevert(bytes(UNAUTHORIZED)); blue.withdraw(market, 1, address(this), address(this)); - vm.expectRevert(bytes(ErrorsLib.UNAUTHORIZED)); + vm.expectRevert(bytes(UNAUTHORIZED)); blue.withdrawCollateral(market, 1, address(this), address(this)); - vm.expectRevert(bytes(ErrorsLib.UNAUTHORIZED)); + vm.expectRevert(bytes(UNAUTHORIZED)); blue.borrow(market, 1, address(this), address(this)); vm.stopPrank(); From 4e33c7d7f77bcef60b3f7f02fa477e37b4546f4c Mon Sep 17 00:00:00 2001 From: MathisGD Date: Thu, 10 Aug 2023 12:09:40 +0200 Subject: [PATCH 5/5] refactor: re-add ErrorsLib --- src/Blue.sol | 75 +++++++++++++++++----------------- src/interfaces/IBlue.sol | 32 --------------- src/libraries/ErrorsLib.sol | 21 ++++++++++ test/forge/Blue.t.sol | 80 ++++++++++++++++++------------------- 4 files changed, 99 insertions(+), 109 deletions(-) create mode 100644 src/libraries/ErrorsLib.sol diff --git a/src/Blue.sol b/src/Blue.sol index fb3d73c89..b778cefba 100644 --- a/src/Blue.sol +++ b/src/Blue.sol @@ -8,6 +8,7 @@ import {IERC20} from "./interfaces/IERC20.sol"; import {IOracle} from "./interfaces/IOracle.sol"; import {UtilsLib} from "./libraries/UtilsLib.sol"; +import {ErrorsLib} from "./libraries/ErrorsLib.sol"; import {MarketLib} from "./libraries/MarketLib.sol"; import {SharesMathLib} from "./libraries/SharesMathLib.sol"; import {SafeTransferLib} from "./libraries/SafeTransferLib.sol"; @@ -77,7 +78,7 @@ contract Blue is IBlue { // Modifiers. modifier onlyOwner() { - require(msg.sender == owner, NOT_OWNER); + require(msg.sender == owner, ErrorsLib.NOT_OWNER); _; } @@ -96,7 +97,7 @@ contract Blue is IBlue { } function enableLltv(uint256 lltv) external onlyOwner { - require(lltv < WAD, LLTV_TOO_HIGH); + require(lltv < WAD, ErrorsLib.LLTV_TOO_HIGH); isLltvEnabled[lltv] = true; emit EnableLltv(lltv); @@ -105,8 +106,8 @@ contract Blue is IBlue { /// @notice It is the owner's responsibility to ensure a fee recipient is set before setting a non-zero fee. function setFee(Market memory market, uint256 newFee) external onlyOwner { Id id = market.id(); - require(lastUpdate[id] != 0, MARKET_NOT_CREATED); - require(newFee <= MAX_FEE, MAX_FEE_EXCEEDED); + require(lastUpdate[id] != 0, ErrorsLib.MARKET_NOT_CREATED); + require(newFee <= MAX_FEE, ErrorsLib.MAX_FEE_EXCEEDED); // Accrue interests using the previous fee set before changing it. _accrueInterests(market, id); @@ -126,9 +127,9 @@ contract Blue is IBlue { function createMarket(Market memory market) external { Id id = market.id(); - require(isIrmEnabled[market.irm], IRM_NOT_ENABLED); - require(isLltvEnabled[market.lltv], LLTV_NOT_ENABLED); - require(lastUpdate[id] == 0, MARKET_CREATED); + require(isIrmEnabled[market.irm], ErrorsLib.IRM_NOT_ENABLED); + require(isLltvEnabled[market.lltv], ErrorsLib.LLTV_NOT_ENABLED); + require(lastUpdate[id] == 0, ErrorsLib.MARKET_CREATED); lastUpdate[id] = block.timestamp; @@ -141,9 +142,9 @@ contract Blue is IBlue { external { Id id = market.id(); - require(lastUpdate[id] != 0, MARKET_NOT_CREATED); - require(UtilsLib.exactlyOneZero(amount, shares), NOT_EXACTLY_ONE_ZERO); - require(onBehalf != address(0), ZERO_ADDRESS); + require(lastUpdate[id] != 0, ErrorsLib.MARKET_NOT_CREATED); + require(UtilsLib.exactlyOneZero(amount, shares), ErrorsLib.NOT_EXACTLY_ONE_ZERO); + require(onBehalf != address(0), ErrorsLib.ZERO_ADDRESS); _accrueInterests(market, id); @@ -165,11 +166,11 @@ contract Blue is IBlue { external { Id id = market.id(); - require(lastUpdate[id] != 0, MARKET_NOT_CREATED); - require(UtilsLib.exactlyOneZero(amount, shares), NOT_EXACTLY_ONE_ZERO); + require(lastUpdate[id] != 0, ErrorsLib.MARKET_NOT_CREATED); + require(UtilsLib.exactlyOneZero(amount, shares), ErrorsLib.NOT_EXACTLY_ONE_ZERO); // No need to verify that onBehalf != address(0) thanks to the authorization check. - require(receiver != address(0), ZERO_ADDRESS); - require(_isSenderAuthorized(onBehalf), UNAUTHORIZED); + require(receiver != address(0), ErrorsLib.ZERO_ADDRESS); + require(_isSenderAuthorized(onBehalf), ErrorsLib.UNAUTHORIZED); _accrueInterests(market, id); @@ -182,7 +183,7 @@ contract Blue is IBlue { emit Withdraw(id, msg.sender, onBehalf, receiver, amount, shares); - require(totalBorrow[id] <= totalSupply[id], INSUFFICIENT_LIQUIDITY); + require(totalBorrow[id] <= totalSupply[id], ErrorsLib.INSUFFICIENT_LIQUIDITY); IERC20(market.borrowableAsset).safeTransfer(receiver, amount); } @@ -193,11 +194,11 @@ contract Blue is IBlue { external { Id id = market.id(); - require(lastUpdate[id] != 0, MARKET_NOT_CREATED); - require(UtilsLib.exactlyOneZero(amount, shares), NOT_EXACTLY_ONE_ZERO); + require(lastUpdate[id] != 0, ErrorsLib.MARKET_NOT_CREATED); + require(UtilsLib.exactlyOneZero(amount, shares), ErrorsLib.NOT_EXACTLY_ONE_ZERO); // No need to verify that onBehalf != address(0) thanks to the authorization check. - require(receiver != address(0), ZERO_ADDRESS); - require(_isSenderAuthorized(onBehalf), UNAUTHORIZED); + require(receiver != address(0), ErrorsLib.ZERO_ADDRESS); + require(_isSenderAuthorized(onBehalf), ErrorsLib.UNAUTHORIZED); _accrueInterests(market, id); @@ -210,8 +211,8 @@ contract Blue is IBlue { emit Borrow(id, msg.sender, onBehalf, receiver, amount, shares); - require(_isHealthy(market, id, onBehalf), INSUFFICIENT_COLLATERAL); - require(totalBorrow[id] <= totalSupply[id], INSUFFICIENT_LIQUIDITY); + require(_isHealthy(market, id, onBehalf), ErrorsLib.INSUFFICIENT_COLLATERAL); + require(totalBorrow[id] <= totalSupply[id], ErrorsLib.INSUFFICIENT_LIQUIDITY); IERC20(market.borrowableAsset).safeTransfer(receiver, amount); } @@ -220,9 +221,9 @@ contract Blue is IBlue { external { Id id = market.id(); - require(lastUpdate[id] != 0, MARKET_NOT_CREATED); - require(UtilsLib.exactlyOneZero(amount, shares), NOT_EXACTLY_ONE_ZERO); - require(onBehalf != address(0), ZERO_ADDRESS); + require(lastUpdate[id] != 0, ErrorsLib.MARKET_NOT_CREATED); + require(UtilsLib.exactlyOneZero(amount, shares), ErrorsLib.NOT_EXACTLY_ONE_ZERO); + require(onBehalf != address(0), ErrorsLib.ZERO_ADDRESS); _accrueInterests(market, id); @@ -245,9 +246,9 @@ contract Blue is IBlue { /// @dev Don't accrue interests because it's not required and it saves gas. function supplyCollateral(Market memory market, uint256 amount, address onBehalf, bytes calldata data) external { Id id = market.id(); - require(lastUpdate[id] != 0, MARKET_NOT_CREATED); - require(amount != 0, ZERO_AMOUNT); - require(onBehalf != address(0), ZERO_ADDRESS); + require(lastUpdate[id] != 0, ErrorsLib.MARKET_NOT_CREATED); + require(amount != 0, ErrorsLib.ZERO_AMOUNT); + require(onBehalf != address(0), ErrorsLib.ZERO_ADDRESS); // Don't accrue interests because it's not required and it saves gas. @@ -262,11 +263,11 @@ contract Blue is IBlue { function withdrawCollateral(Market memory market, uint256 amount, address onBehalf, address receiver) external { Id id = market.id(); - require(lastUpdate[id] != 0, MARKET_NOT_CREATED); - require(amount != 0, ZERO_AMOUNT); + require(lastUpdate[id] != 0, ErrorsLib.MARKET_NOT_CREATED); + require(amount != 0, ErrorsLib.ZERO_AMOUNT); // No need to verify that onBehalf != address(0) thanks to the authorization check. - require(receiver != address(0), ZERO_ADDRESS); - require(_isSenderAuthorized(onBehalf), UNAUTHORIZED); + require(receiver != address(0), ErrorsLib.ZERO_ADDRESS); + require(_isSenderAuthorized(onBehalf), ErrorsLib.UNAUTHORIZED); _accrueInterests(market, id); @@ -274,7 +275,7 @@ contract Blue is IBlue { emit WithdrawCollateral(id, msg.sender, onBehalf, receiver, amount); - require(_isHealthy(market, id, onBehalf), INSUFFICIENT_COLLATERAL); + require(_isHealthy(market, id, onBehalf), ErrorsLib.INSUFFICIENT_COLLATERAL); IERC20(market.collateralAsset).safeTransfer(receiver, amount); } @@ -283,14 +284,14 @@ contract Blue is IBlue { function liquidate(Market memory market, address borrower, uint256 seized, bytes calldata data) external { Id id = market.id(); - require(lastUpdate[id] != 0, MARKET_NOT_CREATED); - require(seized != 0, ZERO_AMOUNT); + require(lastUpdate[id] != 0, ErrorsLib.MARKET_NOT_CREATED); + require(seized != 0, ErrorsLib.ZERO_AMOUNT); _accrueInterests(market, id); (uint256 collateralPrice, uint256 priceScale) = IOracle(market.oracle).price(); - require(!_isHealthy(market, id, borrower, collateralPrice, priceScale), HEALTHY_POSITION); + require(!_isHealthy(market, id, borrower, collateralPrice, priceScale), ErrorsLib.HEALTHY_POSITION); // The liquidation incentive is 1 + ALPHA * (1 / LLTV - 1). uint256 incentive = WAD + ALPHA.wMulDown(WAD.wDivDown(market.lltv) - WAD); @@ -351,7 +352,7 @@ contract Blue is IBlue { uint256 deadline, Signature calldata signature ) external { - require(block.timestamp < deadline, SIGNATURE_EXPIRED); + require(block.timestamp < deadline, ErrorsLib.SIGNATURE_EXPIRED); uint256 usedNonce = nonce[authorizer]++; bytes32 hashStruct = @@ -359,7 +360,7 @@ contract Blue is IBlue { bytes32 digest = keccak256(abi.encodePacked("\x19\x01", DOMAIN_SEPARATOR, hashStruct)); address signatory = ecrecover(digest, signature.v, signature.r, signature.s); - require(signatory != address(0) && authorizer == signatory, INVALID_SIGNATURE); + require(signatory != address(0) && authorizer == signatory, ErrorsLib.INVALID_SIGNATURE); emit IncrementNonce(msg.sender, authorizer, usedNonce); diff --git a/src/interfaces/IBlue.sol b/src/interfaces/IBlue.sol index 712ee9c5f..ccc22c156 100644 --- a/src/interfaces/IBlue.sol +++ b/src/interfaces/IBlue.sol @@ -20,38 +20,6 @@ struct Signature { bytes32 s; } -string constant NOT_OWNER = "not owner"; - -string constant LLTV_TOO_HIGH = "LLTV too high"; - -string constant MAX_FEE_EXCEEDED = "MAX_FEE exceeded"; - -string constant IRM_NOT_ENABLED = "IRM not enabled"; - -string constant LLTV_NOT_ENABLED = "LLTV not enabled"; - -string constant MARKET_CREATED = "market created"; - -string constant MARKET_NOT_CREATED = "market not created"; - -string constant NOT_EXACTLY_ONE_ZERO = "not exactly one zero"; - -string constant ZERO_AMOUNT = "zero amount"; - -string constant ZERO_ADDRESS = "zero address"; - -string constant UNAUTHORIZED = "unauthorized"; - -string constant INSUFFICIENT_COLLATERAL = "insufficient collateral"; - -string constant INSUFFICIENT_LIQUIDITY = "insufficient liquidity"; - -string constant HEALTHY_POSITION = "position is healthy"; - -string constant INVALID_SIGNATURE = "invalid signature"; - -string constant SIGNATURE_EXPIRED = "signature expired"; - interface IBlue is IFlashLender { event SupplyCollateral(Id indexed id, address indexed caller, address indexed onBehalf, uint256 amount); event WithdrawCollateral( diff --git a/src/libraries/ErrorsLib.sol b/src/libraries/ErrorsLib.sol new file mode 100644 index 000000000..b8f8c6e21 --- /dev/null +++ b/src/libraries/ErrorsLib.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.0; + +library ErrorsLib { + string constant NOT_OWNER = "not owner"; + string constant LLTV_TOO_HIGH = "LLTV too high"; + string constant MAX_FEE_EXCEEDED = "MAX_FEE exceeded"; + string constant IRM_NOT_ENABLED = "IRM not enabled"; + string constant LLTV_NOT_ENABLED = "LLTV not enabled"; + string constant MARKET_CREATED = "market created"; + string constant MARKET_NOT_CREATED = "market not created"; + string constant NOT_EXACTLY_ONE_ZERO = "not exactly one zero"; + string constant ZERO_AMOUNT = "zero amount"; + string constant ZERO_ADDRESS = "zero address"; + string constant UNAUTHORIZED = "unauthorized"; + string constant INSUFFICIENT_COLLATERAL = "insufficient collateral"; + string constant INSUFFICIENT_LIQUIDITY = "insufficient liquidity"; + string constant HEALTHY_POSITION = "position is healthy"; + string constant INVALID_SIGNATURE = "invalid signature"; + string constant SIGNATURE_EXPIRED = "signature expired"; +} diff --git a/test/forge/Blue.t.sol b/test/forge/Blue.t.sol index a20c97bf6..e71cd22f3 100644 --- a/test/forge/Blue.t.sol +++ b/test/forge/Blue.t.sol @@ -149,7 +149,7 @@ contract BlueTest is Blue blue2 = new Blue(OWNER); vm.prank(attacker); - vm.expectRevert(bytes(NOT_OWNER)); + vm.expectRevert(bytes(ErrorsLib.NOT_OWNER)); blue2.setOwner(newOwner); } @@ -157,7 +157,7 @@ contract BlueTest is vm.assume(attacker != blue.owner()); vm.prank(attacker); - vm.expectRevert(bytes(NOT_OWNER)); + vm.expectRevert(bytes(ErrorsLib.NOT_OWNER)); blue.enableIrm(newIrm); } @@ -181,7 +181,7 @@ contract BlueTest is vm.assume(marketFuzz.irm != address(irm)); vm.prank(OWNER); - vm.expectRevert(bytes(IRM_NOT_ENABLED)); + vm.expectRevert(bytes(ErrorsLib.IRM_NOT_ENABLED)); blue.createMarket(marketFuzz); } @@ -189,7 +189,7 @@ contract BlueTest is vm.assume(attacker != OWNER); vm.prank(attacker); - vm.expectRevert(bytes(NOT_OWNER)); + vm.expectRevert(bytes(ErrorsLib.NOT_OWNER)); blue.enableLltv(newLltv); } @@ -206,7 +206,7 @@ contract BlueTest is newLltv = bound(newLltv, WAD, type(uint256).max); vm.prank(OWNER); - vm.expectRevert(bytes(LLTV_TOO_HIGH)); + vm.expectRevert(bytes(ErrorsLib.LLTV_TOO_HIGH)); blue.enableLltv(newLltv); } @@ -223,7 +223,7 @@ contract BlueTest is fee = bound(fee, MAX_FEE + 1, type(uint256).max); vm.prank(OWNER); - vm.expectRevert(bytes(MAX_FEE_EXCEEDED)); + vm.expectRevert(bytes(ErrorsLib.MAX_FEE_EXCEEDED)); blue.setFee(market, fee); } @@ -232,7 +232,7 @@ contract BlueTest is fee = bound(fee, 0, WAD); vm.prank(OWNER); - vm.expectRevert(bytes(MARKET_NOT_CREATED)); + vm.expectRevert(bytes(ErrorsLib.MARKET_NOT_CREATED)); blue.setFee(marketFuzz, fee); } @@ -240,7 +240,7 @@ contract BlueTest is vm.assume(caller != OWNER); fee = bound(fee, 0, WAD); - vm.expectRevert(bytes(NOT_OWNER)); + vm.expectRevert(bytes(ErrorsLib.NOT_OWNER)); blue.setFee(market, fee); } @@ -254,7 +254,7 @@ contract BlueTest is function testSetFeeRecipientShouldRevertIfNotOwner(address caller, address recipient) public { vm.assume(caller != OWNER); - vm.expectRevert(bytes(NOT_OWNER)); + vm.expectRevert(bytes(ErrorsLib.NOT_OWNER)); vm.prank(caller); blue.setFeeRecipient(recipient); } @@ -306,7 +306,7 @@ contract BlueTest is marketFuzz.irm = address(irm); vm.prank(OWNER); - vm.expectRevert(bytes(LLTV_NOT_ENABLED)); + vm.expectRevert(bytes(ErrorsLib.LLTV_NOT_ENABLED)); blue.createMarket(marketFuzz); } @@ -354,7 +354,7 @@ contract BlueTest is if (amountBorrowed > amountLent) { vm.prank(BORROWER); - vm.expectRevert(bytes(INSUFFICIENT_LIQUIDITY)); + vm.expectRevert(bytes(ErrorsLib.INSUFFICIENT_LIQUIDITY)); blue.borrow(market, amountBorrowed, 0, BORROWER, receiver); return; } @@ -426,7 +426,7 @@ contract BlueTest is blue.withdraw(market, 0, sharesWithdrawn, address(this), receiver); return; } else if (amountWithdrawn > totalSupplyBefore - amountBorrowed) { - vm.expectRevert(bytes(INSUFFICIENT_LIQUIDITY)); + vm.expectRevert(bytes(ErrorsLib.INSUFFICIENT_LIQUIDITY)); blue.withdraw(market, 0, sharesWithdrawn, address(this), receiver); return; } @@ -604,7 +604,7 @@ contract BlueTest is uint256 maxBorrow = amountCollateral.wMulDown(collateralPrice).wMulDown(LLTV); vm.prank(BORROWER); - if (maxBorrow < amountBorrowed) vm.expectRevert(bytes(INSUFFICIENT_COLLATERAL)); + if (maxBorrow < amountBorrowed) vm.expectRevert(bytes(ErrorsLib.INSUFFICIENT_COLLATERAL)); blue.borrow(market, amountBorrowed, 0, BORROWER, BORROWER); } @@ -727,76 +727,76 @@ contract BlueTest is function testUnknownMarket(Market memory marketFuzz) public { vm.assume(neq(marketFuzz, market)); - vm.expectRevert(bytes(MARKET_NOT_CREATED)); + vm.expectRevert(bytes(ErrorsLib.MARKET_NOT_CREATED)); blue.supply(marketFuzz, 1, 0, address(this), hex""); - vm.expectRevert(bytes(MARKET_NOT_CREATED)); + vm.expectRevert(bytes(ErrorsLib.MARKET_NOT_CREATED)); blue.withdraw(marketFuzz, 1, 0, address(this), address(this)); - vm.expectRevert(bytes(MARKET_NOT_CREATED)); + vm.expectRevert(bytes(ErrorsLib.MARKET_NOT_CREATED)); blue.borrow(marketFuzz, 1, 0, address(this), address(this)); - vm.expectRevert(bytes(MARKET_NOT_CREATED)); + vm.expectRevert(bytes(ErrorsLib.MARKET_NOT_CREATED)); blue.repay(marketFuzz, 1, 0, address(this), hex""); - vm.expectRevert(bytes(MARKET_NOT_CREATED)); + vm.expectRevert(bytes(ErrorsLib.MARKET_NOT_CREATED)); blue.supplyCollateral(marketFuzz, 1, address(this), hex""); - vm.expectRevert(bytes(MARKET_NOT_CREATED)); + vm.expectRevert(bytes(ErrorsLib.MARKET_NOT_CREATED)); blue.withdrawCollateral(marketFuzz, 1, address(this), address(this)); - vm.expectRevert(bytes(MARKET_NOT_CREATED)); + vm.expectRevert(bytes(ErrorsLib.MARKET_NOT_CREATED)); blue.liquidate(marketFuzz, address(0), 1, hex""); } function testInputZero() public { - vm.expectRevert(bytes(NOT_EXACTLY_ONE_ZERO)); + vm.expectRevert(bytes(ErrorsLib.NOT_EXACTLY_ONE_ZERO)); blue.supply(market, 0, 0, address(this), hex""); - vm.expectRevert(bytes(NOT_EXACTLY_ONE_ZERO)); + vm.expectRevert(bytes(ErrorsLib.NOT_EXACTLY_ONE_ZERO)); blue.supply(market, 1, 1, address(this), hex""); - vm.expectRevert(bytes(NOT_EXACTLY_ONE_ZERO)); + vm.expectRevert(bytes(ErrorsLib.NOT_EXACTLY_ONE_ZERO)); blue.withdraw(market, 0, 0, address(this), address(this)); - vm.expectRevert(bytes(NOT_EXACTLY_ONE_ZERO)); + vm.expectRevert(bytes(ErrorsLib.NOT_EXACTLY_ONE_ZERO)); blue.withdraw(market, 1, 1, address(this), address(this)); - vm.expectRevert(bytes(NOT_EXACTLY_ONE_ZERO)); + vm.expectRevert(bytes(ErrorsLib.NOT_EXACTLY_ONE_ZERO)); blue.borrow(market, 0, 0, address(this), address(this)); - vm.expectRevert(bytes(NOT_EXACTLY_ONE_ZERO)); + vm.expectRevert(bytes(ErrorsLib.NOT_EXACTLY_ONE_ZERO)); blue.borrow(market, 1, 1, address(this), address(this)); - vm.expectRevert(bytes(NOT_EXACTLY_ONE_ZERO)); + vm.expectRevert(bytes(ErrorsLib.NOT_EXACTLY_ONE_ZERO)); blue.repay(market, 0, 0, address(this), hex""); - vm.expectRevert(bytes(NOT_EXACTLY_ONE_ZERO)); + vm.expectRevert(bytes(ErrorsLib.NOT_EXACTLY_ONE_ZERO)); blue.repay(market, 1, 1, address(this), hex""); - vm.expectRevert(bytes(ZERO_AMOUNT)); + vm.expectRevert(bytes(ErrorsLib.ZERO_AMOUNT)); blue.supplyCollateral(market, 0, address(this), hex""); - vm.expectRevert(bytes(ZERO_AMOUNT)); + vm.expectRevert(bytes(ErrorsLib.ZERO_AMOUNT)); blue.withdrawCollateral(market, 0, address(this), address(this)); - vm.expectRevert(bytes(ZERO_AMOUNT)); + vm.expectRevert(bytes(ErrorsLib.ZERO_AMOUNT)); blue.liquidate(market, address(0), 0, hex""); } function testZeroAddress() public { - vm.expectRevert(bytes(ZERO_ADDRESS)); + vm.expectRevert(bytes(ErrorsLib.ZERO_ADDRESS)); blue.supply(market, 0, 1, address(0), hex""); - vm.expectRevert(bytes(ZERO_ADDRESS)); + vm.expectRevert(bytes(ErrorsLib.ZERO_ADDRESS)); blue.withdraw(market, 0, 1, address(this), address(0)); - vm.expectRevert(bytes(ZERO_ADDRESS)); + vm.expectRevert(bytes(ErrorsLib.ZERO_ADDRESS)); blue.borrow(market, 0, 1, address(this), address(0)); - vm.expectRevert(bytes(ZERO_ADDRESS)); + vm.expectRevert(bytes(ErrorsLib.ZERO_ADDRESS)); blue.repay(market, 0, 1, address(0), hex""); - vm.expectRevert(bytes(ZERO_ADDRESS)); + vm.expectRevert(bytes(ErrorsLib.ZERO_ADDRESS)); blue.supplyCollateral(market, 1, address(0), hex""); - vm.expectRevert(bytes(ZERO_ADDRESS)); + vm.expectRevert(bytes(ErrorsLib.ZERO_ADDRESS)); blue.withdrawCollateral(market, 1, address(this), address(0)); } @@ -823,11 +823,11 @@ contract BlueTest is vm.startPrank(attacker); - vm.expectRevert(bytes(UNAUTHORIZED)); + vm.expectRevert(bytes(ErrorsLib.UNAUTHORIZED)); blue.withdraw(market, 0, 1, address(this), address(this)); - vm.expectRevert(bytes(UNAUTHORIZED)); + vm.expectRevert(bytes(ErrorsLib.UNAUTHORIZED)); blue.withdrawCollateral(market, 1, address(this), address(this)); - vm.expectRevert(bytes(UNAUTHORIZED)); + vm.expectRevert(bytes(ErrorsLib.UNAUTHORIZED)); blue.borrow(market, 0, 1, address(this), address(this)); vm.stopPrank();