From 9b1c70ef630cf6d6a0acc3d681180e08bdeda80a Mon Sep 17 00:00:00 2001 From: q1q0 Date: Sat, 18 Nov 2023 14:17:48 -0500 Subject: [PATCH] update approve function --- .../connectors/morpho-blue/helpers.sol | 22 +++++++ .../connectors/morpho-blue/interface.sol | 15 +++++ .../mainnet/connectors/morpho-blue/main.sol | 60 +++++++++++++++---- 3 files changed, 86 insertions(+), 11 deletions(-) diff --git a/contracts/mainnet/connectors/morpho-blue/helpers.sol b/contracts/mainnet/connectors/morpho-blue/helpers.sol index 2b71103c..ef0f0500 100644 --- a/contracts/mainnet/connectors/morpho-blue/helpers.sol +++ b/contracts/mainnet/connectors/morpho-blue/helpers.sol @@ -34,10 +34,32 @@ abstract contract Helpers is Stores, Basic { uint256 internal constant MARKET_PARAMS_BYTES_LENGTH = 5 * 32; + /// @dev A number of virtual assets of 1 enforces a conversion rate between shares and assets when a market is + /// empty. + uint256 internal constant VIRTUAL_ASSETS = 1; + + /// @dev The number of virtual shares has been chosen low enough to prevent overflows, and high enough to ensure + /// high precision computations. + uint256 internal constant VIRTUAL_SHARES = 1e6; + /// @notice Returns the id of the market `marketParams`. function id(MarketParams memory marketParams) internal pure returns (bytes32 marketParamsId) { assembly { marketParamsId := keccak256(marketParams, MARKET_PARAMS_BYTES_LENGTH) } } + + /// @dev Calculates the value of `shares` quoted in assets, rounding up. + function _toAssetsUp(uint256 _shares, uint256 _totalAssets, uint256 _totalShares) internal pure returns (uint256) { + return _mulDivUp(_shares, _totalAssets + VIRTUAL_ASSETS, _totalShares + VIRTUAL_SHARES); + } + + /// @dev Returns (`x` * `y`) / `d` rounded up. + function _mulDivUp(uint256 x, uint256 y, uint256 d) internal pure returns (uint256) { + return (x * y + (d - 1)) / d; + } + + function _getApproveAmount(bytes32 _id, uint256 _assets, uint256 _shares) internal view returns (uint256 _amount) { + _amount == 0 ? _assets = _toAssetsUp(_shares, MORPHO_BLUE.market(_id).totalSupplyAssets, MORPHO_BLUE.market(_id).totalSupplyShares) : _assets; + } } diff --git a/contracts/mainnet/connectors/morpho-blue/interface.sol b/contracts/mainnet/connectors/morpho-blue/interface.sol index 68e9bb62..b30932be 100644 --- a/contracts/mainnet/connectors/morpho-blue/interface.sol +++ b/contracts/mainnet/connectors/morpho-blue/interface.sol @@ -20,6 +20,19 @@ struct Position { uint128 collateral; } +/// @dev Warning: `totalSupplyAssets` does not contain the accrued interest since the last interest accrual. +/// @dev Warning: `totalBorrowAssets` does not contain the accrued interest since the last interest accrual. +/// @dev Warning: `totalSupplyShares` does not contain the additional shares accrued by `feeRecipient` since the last +/// interest accrual. +struct Market { + uint128 totalSupplyAssets; + uint128 totalSupplyShares; + uint128 totalBorrowAssets; + uint128 totalBorrowShares; + uint128 lastUpdate; + uint128 fee; +} + interface IMorpho { function createMarket(MarketParams memory marketParams) external; @@ -61,5 +74,7 @@ interface IMorpho { function withdrawCollateral(MarketParams memory marketParams, uint256 assets, address onBehalf, address receiver) external; function position(bytes32 id, address user) external view returns(Position memory); + + function market(bytes32 id) external view returns(Market memory); } diff --git a/contracts/mainnet/connectors/morpho-blue/main.sol b/contracts/mainnet/connectors/morpho-blue/main.sol index 8ce5508a..d3b0abde 100644 --- a/contracts/mainnet/connectors/morpho-blue/main.sol +++ b/contracts/mainnet/connectors/morpho-blue/main.sol @@ -39,11 +39,13 @@ abstract contract MorphoBlue is Helpers, Events { TokenInterface _tokenContract, uint256 _amt, ) = _performEthToWethConversion(_marketParams.loanToken, _assets, _getId); - - approve(_tokenContract, address(MORPHO_BLUE), _amt); + + bytes32 _id = id(_marketParams); + uint256 _approveAmount = _getApproveAmount(_id, _amt, _shares); + approve(_tokenContract, address(MORPHO_BLUE), _approveAmount); _marketParams.loanToken = address(_tokenContract); - (_assets, _shares) = MORPHO_BLUE.supply(_marketParams, _assets, _shares, address(this), _data); + (_assets, _shares) = MORPHO_BLUE.supply(_marketParams, _amt, _shares, address(this), _data); setUint(_setId, _amt); @@ -85,9 +87,11 @@ abstract contract MorphoBlue is Helpers, Events { { uint256 _amt = getUint(_getId, _assets); - approve(TokenInterface(_marketParams.loanToken), address(MORPHO_BLUE), _amt); + bytes32 _id = id(_marketParams); + uint256 _approveAmount = _getApproveAmount(_id, _amt, _shares); + approve(TokenInterface(_marketParams.loanToken), address(MORPHO_BLUE), _approveAmount); - (_assets, _shares) = MORPHO_BLUE.supply(_marketParams, _assets, _shares, _onBehalf, _data); + (_assets, _shares) = MORPHO_BLUE.supply(_marketParams, _amt, _shares, _onBehalf, _data); setUint(_setId, _amt); @@ -130,7 +134,7 @@ abstract contract MorphoBlue is Helpers, Events { approve(_tokenContract, address(MORPHO_BLUE), _amt); _marketParams.loanToken = address(_tokenContract); - MORPHO_BLUE.supplyCollateral(_marketParams, _assets, address(this), _data); + MORPHO_BLUE.supplyCollateral(_marketParams, _amt, address(this), _data); setUint(_setId, _amt); @@ -170,7 +174,7 @@ abstract contract MorphoBlue is Helpers, Events { approve(TokenInterface(_marketParams.loanToken), address(MORPHO_BLUE), _amt); - MORPHO_BLUE.supplyCollateral(_marketParams, _assets, _onBehalf, _data); + MORPHO_BLUE.supplyCollateral(_marketParams, _amt, _onBehalf, _data); setUint(_setId, _amt); @@ -488,9 +492,27 @@ abstract contract MorphoBlue is Helpers, Events { address _oldLoanToken = _marketParams.loanToken; _marketParams.loanToken = address(_tokenContract); - approve(TokenInterface(_marketParams.loanToken), address(MORPHO_BLUE), _amt); + if (_isMax) { + _assets = 0; + _shares = _amt; + } else { + _assets = _amt; + } + { + bytes32 _id = id(_marketParams); + uint256 _approveAmount = _getApproveAmount(_id, _assets, _shares); - (_assets, _shares) = MORPHO_BLUE.repay(_marketParams, (_isMax ? 0 : _amt), (_isMax ? _amt : _shares), address(this), _data); + approve(TokenInterface(_marketParams.loanToken), address(MORPHO_BLUE), _approveAmount); + } + + + (_assets, _shares) = MORPHO_BLUE.repay( + _marketParams, + _assets, + _shares, + address(this), + _data + ); convertWethToEth(_oldLoanToken == ethAddr, TokenInterface(wethAddr), _amt); @@ -539,9 +561,25 @@ abstract contract MorphoBlue is Helpers, Events { _isMax = true; } - approve(TokenInterface(_marketParams.loanToken), address(MORPHO_BLUE), _amt); + if (_isMax) { + _assets = 0; + _shares = _amt; + } else { + _assets = _amt; + } - (_assets, _shares) = MORPHO_BLUE.repay(_marketParams, (_isMax ? 0 : _amt), (_isMax ? _amt : _shares), address(this), _data); + bytes32 _id = id(_marketParams); + uint256 _approveAmount = _getApproveAmount(_id, _assets, _shares); + + approve(TokenInterface(_marketParams.loanToken), address(MORPHO_BLUE), _approveAmount); + + (_assets, _shares) = MORPHO_BLUE.repay( + _marketParams, + _assets, + _shares, + address(this), + _data + ); setUint(_setId, _amt);