Manage
Please read the README section from the repository.
As a reminder, the following snippets are for educational purposes.
Summary
Overview of the snippets implementation of a smart contract exposing the following functions:
depositInVault
Deposit assets
into the vault
on behalf of onBehalf
.
withdrawFromVaultAmount
Withdraws assets
from the vault
on behalf of the sender, and sends them to receiver
.
redeemAllFromVault
Redeems the whole sender's position from the vault
, and sends the withdrawn amount to receiver
.
reallocateAvailableLiquidity
Withdraws the maximum available liquidity from the markets srcMarketParams
, and supply the withdrawn assets into destMarketParams
.
- Solidity (Foundry)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {IMetaMorpho, MarketAllocation} from "@metamorpho/interfaces/IMetaMorpho.sol";
import {MarketParamsLib} from "../../lib/metamorpho/lib/morpho-blue/src/libraries/MarketParamsLib.sol";
import {IMorpho} from "../../lib/metamorpho/lib/morpho-blue/src/interfaces/IMorpho.sol";
import {ERC20} from "@openzeppelin/token/ERC20/ERC20.sol";
contract MetaMorphoSnippets {
IMorpho public immutable morpho;
constructor(address morphoAddress) {
morpho = IMorpho(morphoAddress);
}
/// @notice Deposit `assets` into the `vault` on behalf of `onBehalf`.
/// @dev Sender must approve the snippets contract to manage his tokens before the call.
/// @param vault The address of the Morpho Vault.
/// @param assets the amount to deposit.
/// @param onBehalf The address that will own the increased deposit position.
function depositInVault(address vault, uint256 assets, address onBehalf) public returns (uint256 shares) {
ERC20(IMetaMorpho(vault).asset()).transferFrom(msg.sender, address(this), assets);
_approveMaxVault(vault);
shares = IMetaMorpho(vault).deposit(assets, onBehalf);
}
/// @notice Withdraws `assets` from the `vault` on behalf of the sender, and sends them to `receiver`.
/// @dev Sender must approve the snippets contract to manage his tokens before the call.
/// @dev To withdraw all, it is recommended to use the redeem function.
/// @param vault The address of the Morpho Vault.
/// @param assets the amount to withdraw.
/// @param receiver The address that will receive the withdrawn assets.
function withdrawFromVaultAmount(address vault, uint256 assets, address receiver)
public
returns (uint256 redeemed)
{
redeemed = IMetaMorpho(vault).withdraw(assets, receiver, msg.sender);
}
/// @notice Redeems the whole sender's position from the `vault`, and sends the withdrawn amount to `receiver`.
/// @param vault The address of the Morpho Vault.
/// @param receiver The address that will receive the withdrawn assets.
function redeemAllFromVault(address vault, address receiver) public returns (uint256 redeemed) {
uint256 maxToRedeem = IMetaMorpho(vault).maxRedeem(msg.sender);
redeemed = IMetaMorpho(vault).redeem(maxToRedeem, receiver, msg.sender);
}
/// @notice Withdraws the maximum available liquidity from the markets `srcMarketParams`, and supply the withdrawn
/// assets into `destMarketParams`.
/// @dev The contract implementing this function must be registered as an allocator of the vault for the function to
/// be called successfully.
/// @param vault The address of the Morpho Vault.
/// @param srcMarketParams A MarketParams list of markets to withdraw from.
/// @param destMarketParams The MarketParams of the market to supply to.
function reallocateAvailableLiquidity(
address vault,
MarketParams[] calldata srcMarketParams,
MarketParams calldata destMarketParams
) public {
uint256 nbMarkets = srcMarketParams.length;
MarketAllocation[] memory allocations = new MarketAllocation[](nbMarkets + 1);
for (uint256 i; i < nbMarkets; ++i) {
MarketParams memory marketParams = srcMarketParams[i];
(uint256 totalSupplyAssets, uint256 totalSupplyShares, uint256 totalBorrowAssets,) =
morpho.expectedMarketBalances(marketParams);
uint256 supplyShares = morpho.supplyShares(marketParams.id(), vault);
uint256 supplyAssets = supplyShares.toAssetsDown(totalSupplyAssets, totalSupplyShares);
uint256 availableLiquidity = totalSupplyAssets - totalBorrowAssets;
allocations[i] =
MarketAllocation({marketParams: marketParams, assets: supplyAssets.zeroFloorSub(availableLiquidity)});
}
allocations[nbMarkets] = MarketAllocation({marketParams: destMarketParams, assets: type(uint256).max});
IMetaMorpho(vault).reallocate(allocations);
}
function _approveMaxVault(address vault) internal {
if (ERC20(IMetaMorpho(vault).asset()).allowance(address(this), vault) == 0) {
ERC20(IMetaMorpho(vault).asset()).approve(vault, type(uint256).max);
}
}
}