Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Morpho blue #321

Closed
wants to merge 14 commits into from
Closed

Morpho blue #321

wants to merge 14 commits into from

Conversation

shriyatyagii
Copy link
Member

@shriyatyagii shriyatyagii commented Nov 28, 2023

  • Add Morpho Blue connectors and test script

Copy link

Finished status checks

Copy link

github-actions bot commented Dec 9, 2023

Finished status checks

Copy link

Finished status checks

Copy link

Finished status checks

Copy link

Finished status checks


(uint256 _assets, ) = MORPHO_BLUE.supply(
_marketParams,
_amt,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be set to 0 right?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You mean the _amt value? So I've converted the shares value to assets amount to give the approval to Morpho's contract. That's why sending the converted assets value in the function.

Comment on lines +421 to +431
if (_amt == type(uint256).max) {
bytes32 _id = id(_marketParams);
Position memory _pos = MORPHO_BLUE.position(_id, address(this));
uint256 _shares = _pos.supplyShares;

_amt = _toAssetsUp(
_shares,
MORPHO_BLUE.market(_id).totalSupplyAssets,
MORPHO_BLUE.market(_id).totalSupplyShares
);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

when withdrawing max it's advised to use shares instead to make sure no dust is left on the contract

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it!
Updated the logics to use shares in case of max amounts. Here

Position memory _pos = MORPHO_BLUE.position(_id, _onBehalf);
uint256 _shares = _pos.supplyShares;

_amt = _toAssetsUp(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same comment as for withdraw

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated here

Comment on lines +896 to +897
_assetsAmt,
0,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
_assetsAmt,
0,
0,
_shares,

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not using the _shares amount as that can be sent as type(uint256).max, so using the converted assets value instead.

Although I think similar to withdraw, assets value might cause dust amount issues here?

* @param _getId ID to retrieve amt.
* @param _setId ID stores the amount of tokens repaid.
*/
function repayOnBehalfShares(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there's no way to repay max similar to the withdraw max feature?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The max repayment logics are being handled inside the _performEthToWeth conversion functions. It will check the minimum of balance and the debt amount and use that to repay. Logic can be found here.


_assets = _toAssetsUp(
_shareAmt,
MORPHO_BLUE.market(_id).totalSupplyAssets,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does not take into account the interest generated see a similar comment below

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated. Same as this


contract Events {
event LogSupplyAssets(
MarketParams marketParams,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't it be interesting to instead log the market's id and have it indexed?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes! I was calculating id() in the functions only when needed so that's why I didn't add by default. But yes indexing it can be a good option. Updated it here

enum Mode {
Collateral,
Repay,
Other // Neither collateral nor repay
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Neither collateral nor repay mode could be named Loan

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even more specific as it is used only upon supply: Supply

Copy link
Member Author

@shriyatyagii shriyatyagii Dec 16, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed! Here

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Resolved!

Comment on lines +62 to +63
if (_isEth) {
convertEthToWeth(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The value of _isEth is checked twice: once here and once inside convertEthToWeth

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch! Removed the external check. Here

Comment on lines +171 to +178
/// @notice Returns (`x` * `y`) / `d` rounded up.
function _mulDivUp(
uint256 x,
uint256 y,
uint256 d
) internal pure returns (uint256) {
return (x * y + (d - 1)) / d;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

@shriyatyagii shriyatyagii Dec 16, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was not needed anymore since I'm using toAssetsUp directly from Morpho Blue's library. Removed it.

Comment on lines +145 to +155
/// @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
)
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated! Same reason as this

Comment on lines +136 to +142
uint256 _shareAmt = MORPHO_BLUE.position(_id, _onBehalf).supplyShares;

_assets = _toAssetsUp(
_shareAmt,
MORPHO_BLUE.market(_id).totalSupplyAssets,
MORPHO_BLUE.market(_id).totalSupplyShares
);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interest to be accrued is not taken into account here
Besides, it seems the payback balance would correspond to the amount to be repaid on the borrow side, not the supply side
Moreover, market is called twice on MORPHO which costs a lot of SLOAD so a lot of gas

This flow could be optimized and simplified using our audited MorphoBalancesLib: https://github.com/morpho-org/morpho-blue/blob/414b67a523dbc72144a5dfed62ac60771f15d98e/src/libraries/periphery/MorphoBalancesLib.sol#L28-L62

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yes! Updated logic here

Comment on lines +124 to +127
/// @notice Helper function to find the minimum of two values
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes! I had not imported the libraries due to solidity version conflicts with our common files. Using the libraries now.
Code

Comment on lines +105 to +109
_assets = _toAssetsUp(
_shareAmt,
MORPHO_BLUE.market(_id).totalSupplyAssets,
MORPHO_BLUE.market(_id).totalSupplyShares
);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interest to be accrued is not taken into account here
Moreover, market is called twice on MORPHO which costs a lot of SLOAD so a lot of gas

This flow could be optimized and simplified using our audited MorphoBalancesLib: https://github.com/morpho-org/morpho-blue/blob/414b67a523dbc72144a5dfed62ac60771f15d98e/src/libraries/periphery/MorphoBalancesLib.sol#L28-L62

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Didn't realize these are the non accrued interest values. I've imported the necessary libraries and updated calculations to use expectedMarketBalances.
Here

Comment on lines +379 to +384
if (_receiver == address(this))
convertWethToEth(
_marketParams.collateralToken == ethAddr,
TokenInterface(wethAddr),
_amt
);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why always converting weth to eth ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Conversion is only happening in case the token addresses sent from our UI for loan (or collateral) is ETH (0xeee...). We allow users to use ETH tokens for the WETH markets and do the Weth to Eth conversion internally.

Copy link

Stale pull request message

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging this pull request may close these issues.

4 participants