"Combo Meal" — 2+ Recipes

Combo Meals are the final frontier — every zkApp Chef's dream. They combine Recipes into very complex interactions, made 100% safe for execution against a private balance using the Cookbook.

For example, there is a Combo Meal that combines an "Add Liquidity" Recipe for Uniswap, with a "Deposit Vault" Recipe for Beefy. This gives a user the ability to add liquidity for a token pair on Uniswap, gain the LP token for that pair, and then deposit the LP token into a Beefy Vault to earn yield.

This all occurs in a single validated transaction call, saving network fees and making the user experience simple and delightful.

Annotated Example: Uniswap V2-Like (Add Liquidity) and Beefy Vault (Deposit LP Token)

export class UniV2LikeAddLiquidity_BeefyDeposit_ComboMeal extends ComboMeal {
  // Simple name and description. Note that the name of the Uniswap clone is set
  // in the constructor.
  readonly config = {
    name: '[NAME] Add Liquidity + Beefy Vault Deposit Combo Meal',
    description:
      'Adds liquidity to a [NAME] Pool and deposits the LP tokens into a Beefy Vault.',
  };

  // Private variables set during the constructor.
  // In this case, it's a store for the two Recipes that we will combine together.
  private readonly uniV2LikeAddLiquidityRecipe: UniV2LikeAddLiquidityRecipe;
  private readonly beefyDepositRecipe: BeefyDepositRecipe;

  constructor(
    uniswapV2Fork: UniswapV2Fork,
    erc20InfoA: RecipeERC20Info,
    erc20InfoB: RecipeERC20Info,
    slippagePercentage: number,
    vaultID: string,
    provider: BaseProvider,
  ) {
    super();

    // The Recipes are fully initialized here. Note that 
    // input amounts are never passed into Recipe/Combo constructors.
    this.uniV2LikeAddLiquidityRecipe = new UniV2LikeAddLiquidityRecipe(
      uniswapV2Fork,
      erc20InfoA,
      erc20InfoB,
      slippagePercentage,
      provider,
    );
    this.beefyDepositRecipe = new BeefyDepositRecipe(vaultID);

    const forkName = UniV2LikeSDK.getForkName(uniswapV2Fork);
    this.config.name = `${forkName} Add Liquidity + Beefy Vault Deposit Combo Meal`;
    this.config.description = `Adds liquidity to a ${forkName} Pool and deposits the LP tokens into a Beefy Vault.`;
  }

  // This is a helper function that helps a user know how much of "ERC20 B" to unshield
  // for a given amount of "ERC20 A" (A and B make up the liquidity pair).
  // Accuracy is important, as the unshielding operation incurs a small % fee.
  getAddLiquidityAmountBForUnshield(
    networkName: NetworkName,
    targetUnshieldERC20AmountA: RecipeERC20Amount,
  ) {
    return this.uniV2LikeAddLiquidityRecipe.getAddLiquidityAmountBForUnshield(
      networkName,
      targetUnshieldERC20AmountA,
    );
  }

  // Returns the two Recipes that create this "Combo Meal." The steps of each 
  // Recipe will be strung together in series, and sandwiched altogether 
  // by an unshield and shield call. The outputs from the 1st Recipe will not 
  // get automatically re-shielded - they will get passed into the 2nd Recipe 
  // as inputs for its first step.
  // In this way, we can create in a single transaction call, minimizing fees and 
  // building a complex DeFi behavior as a sum of simple parts.
  protected async getRecipes(): Promise<Recipe[]> {
    return [this.uniV2LikeAddLiquidityRecipe, this.beefyDepositRecipe];
  }
}

Last updated