๐Ÿคน

Refinance Maker Vault to Liquity Trove

๐ŸŒŸ
This recipe was shared by Liquity in this blogpost

This recipe refinances a Maker ETH-A Vault by utilizing a flashloan to pay back the debt and re-creates the position in Liquity.

CODE SNIPPIT

const ETH_ADDRESS = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"
const DAI_TOKEN_ADDRESS = "0x6b175474e89094c44da98b954eedeac495271d0f"
const LUSD_TOKEN_ADDRESS = "0x5f98805A4E8be255a32880FDeC7F6728C6568bA0"

const migrateMakerVaultToLiquity = (dsa, helpers, vaultId) => { 

  // 1. Look up how much collateral and debt exists in the Maker vault
  const vault = await helpers.getMakerResolver().getVaultById(vaultId)
  const vaultCollateral = vault.ink
  const vaultDebt = vault.debt

  // 2. Next we flash loan the same amount of ETH as the Maker vault collateral
  // so that we can open a Liquity Trove with the same amount.
  // NB: We declare this spell at the end of the script, with all the spells
  // which follow the flash loan as "child" transactions of the flashloan.

  // 3. Create a Trove using the flashloaned ETH, and borrow LUSD
  const maxFeePercentage = ethers.utils.parseUnits("0.5", 18)
  const { upperHint, lowerHint } = await helpers.getTroveInsertionHints(
    vaultCollateral,
    vaultDebt
  )
  
  const openTroveSpell = {
    connector: "LIQUITY-A",
    method: "open",
    args: [
      vaultCollateral,
      maxFeePercentage,
      vaultDebt,
      upperHint,
      lowerHint,
      [0, 0],
      [0, 0],
    ],
  }

  // 4. Swap the borrowed LUSD for DAI
  const lusdSwapDetails = await helpers.fetch1inchQuote(
    LUSD_TOKEN_ADDRESS,
    DAI_TOKEN_ADDRESS,
    vaultDebt,
    dsa.address
  )

  const swapLusdForDaiSpell = {
    connector: "1INCH-A",
    method: "sell",
    args: [
      DAI_TOKEN_ADDRESS,
      LUSD_TOKEN_ADDRESS,
      vaultDebt,
      lusdSwapDetails.unitAmount,
      lusdSwapDetails.calldata,
      0,
    ],
  }

  // 5. Repay all the Maker vault DAI debt
  const repayMakerDebtSpell = {
    connector: "MAKERDAO-A",
    method: "payback",
    args: [
      vaultId,
      ethers.constants.MaxUint256,
      0,
      0,
    ],
  }

  // 6. Withdraw all the Maker vault ETH collateral
  const withdrawMakerCollateralSpell = {
    connector: "MAKERDAO-A",
    method: "withdraw",
    args: [
      vaultId,
      vaultCollateral,
      0,
      0,
    ],
  }

  // 7. Repay ETH flash loan
  const paybackFlashLoanSpell = {
    connector: "INSTAPOOL-A",
    method: "flashPayback",
    args: [ETH_ADDRESS, vaultCollateral, 0, 0],
  }

  const encodedMigrationSpells = helpers.encodeFlashcastData([
    openTroveSpell,
    swapLusdForDaiSpell,
    repayMakerDebtSpell,
    withdrawMakerCollateralSpell,
    paybackFlashLoanSpell,
  ])

  // 2. Flash loan ETH so we can open a Liquity Trove
  // NB: This spell also holds all the other spells that need
  // to be executed inside the flash loan
  const flashloanWithSpells = [
    {
      connector: "INSTAPOOL-A",
      method: "flashBorrowAndCast",
      args: [
        ETH_ADDRESS,
        vaultCollateral,
        0, // route 0 is an ETH flash loan
        encodedMigrationSpells,
      ],
    },
  ]  

  const spells = dsa.Spell()

  spells.add(flashloanWithSpells)
  
  await spells.cast() // Executes the recipe of spells on the user's DSA account
}