Skip to main content

Understanding and Implementing Bundlers in Solidity

This tutorial will walk you through the implementation of a Morpho Bundler contract in Solidity, explaining key concepts and functionalities.

Overview

The MorphoBundler contract is designed to bundle multiple Morpho operations into a single transaction, improving efficiency and user experience.

Key Components

  1. Imports and Inheritance

    import {IMorphoBundler} from "./interfaces/IMorphoBundler.sol";
    import {MarketParams, Signature, Authorization, IMorpho} from "../lib/morpho-blue/src/interfaces/IMorpho.sol";
    import {ErrorsLib} from "./libraries/ErrorsLib.sol";
    import {SafeTransferLib, ERC20} from "../lib/solmate/src/utils/SafeTransferLib.sol";
    import {BaseBundler} from "./BaseBundler.sol";

    abstract contract MorphoBundler is BaseBundler, IMorphoBundler {
    // Contract body
    }
  2. State Variables

    IMorpho public immutable MORPHO;
  3. Constructor

    constructor(address morpho) {
    require(morpho != address(0), ErrorsLib.ZERO_ADDRESS);
    MORPHO = IMorpho(morpho);
    }

Key Functions

  1. morphoSupply: Supply assets to a Morpho market
  2. morphoSupplyCollateral: Supply collateral to a Morpho market
  3. morphoBorrow: Borrow assets from a Morpho market
  4. morphoRepay: Repay borrowed assets
  5. morphoWithdraw: Withdraw supplied assets
  6. morphoWithdrawCollateral: Withdraw supplied collateral
  7. morphoLiquidate: Perform a liquidation
  8. morphoFlashLoan: Execute a flash loan

Example: morphoSupply Function

function morphoSupply(
MarketParams calldata marketParams,
uint256 assets,
uint256 shares,
uint256 slippageAmount,
address onBehalf,
bytes calldata data
) external payable protected {
require(onBehalf != address(this), ErrorsLib.BUNDLER_ADDRESS);

if (assets == type(uint256).max) assets = ERC20(marketParams.loanToken).balanceOf(address(this));

_approveMaxTo(marketParams.loanToken, address(MORPHO));

(uint256 suppliedAssets, uint256 suppliedShares) = MORPHO.supply(marketParams, assets, shares, onBehalf, data);

if (assets > 0) require(suppliedShares >= slippageAmount, ErrorsLib.SLIPPAGE_EXCEEDED);
else require(suppliedAssets <= slippageAmount, ErrorsLib.SLIPPAGE_EXCEEDED);
}

This function demonstrates how to supply assets to a Morpho market, handling maximum asset amounts, approvals, and slippage checks.

Best Practices

  1. Use require statements for input validation
  2. Implement slippage protection
  3. Use payable and protected modifiers for flexibility and security
  4. Leverage the _approveMaxTo function for token approvals

By understanding and implementing these concepts, you can create efficient and secure bundler contracts for Morpho.