Skip to main content
This example shows minting wsrUSD on Ethereum’s canonical contract and routing to external yield infrastructure through automated bridging and vault deposit sequences. Route Mechanics: This yield strategy orchestrates multiple protocols across Ethereum Mainnet and Katana:
  • Convert USDC to wsrUSD on Ethereum using Enso’s swap routing
  • Bridge wsrUSD from Ethereum to Katana chain via Stargate protocol
  • Check wsrUSD balance on Katana after bridge completion
  • Swap wsrUSD for vault-bridged USDC (vbUSDC) using Enso routing
  • Deposit vbUSDC into Yearn V3 vault for automated yield optimization strategies
const KATANA_ID = 747474;
const ETHEREUM_ID = 1;

// Common addresses
const WALLET_ADDRESS = "0x93621DCA56fE26Cdee86e4F6B18E116e9758Ff11"; // User wallet

// Token addresses
const yvvbUSDC_KATANA = "0x80c34BD3A3569E126e7055831036aa7b212cB159";
const vbUSDC_KATANA = "0x203A662b0BD271A6ed5a60EdFbd04bFce608FD36";
const USDC_ETHEREUM = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48";
const wsrUSD_KATANA = "0x4809010926aec940b550D34a46A52739f996D75D";
const wsrUSD_ETHEREUM = "0xd3fd63209fa2d55b07a0f6db36c2f43900be3094";

const client = new EnsoClient({
  apiKey: process.env.ENSO_API_KEY!,
});

// LayerZero pool addresses
const wsrEthToKatanaPools = await client.getLayerZeroPool({
  chainId: ETHEREUM_ID,
  token: wsrUSD_ETHEREUM,
  destinationChainId: KATANA_ID,
  destinationToken: wsrUSD_KATANA,
});

console.log(JSON.stringify(wsrEthToKatanaPools), !wsrEthToKatanaPools.length);

if (!wsrEthToKatanaPools.length) {
  throw new Error("Required pools not available");
}

const bundle = await client.getBundleData(
  {
    chainId: ETHEREUM_ID,
    fromAddress: WALLET_ADDRESS,
    spender: WALLET_ADDRESS,
    routingStrategy: "router",
  },
  [
    // mint wsrUSD on Ethereum
    {
      protocol: "enso",
      action: "route",
      args: {
        amountIn: parseUnits("1000", 6).toString(), // 1000 USDC
        tokenIn: USDC_ETHEREUM,
        receiver: WALLET_ADDRESS,
        tokenOut: wsrUSD_ETHEREUM,
      },
    },
    {
      protocol: "stargate",
      action: "bridge",
      args: {
        primaryAddress: wsrEthToKatanaPools[0].pool as Address,
        destinationChainId: KATANA_ID,
        tokenIn: wsrUSD_ETHEREUM,
        amountIn: { useOutputOfCallAt: 0 },
        receiver: WALLET_ADDRESS,
        callback: [
          // Step 1: Check wsrUSD balance on Katana after bridge
          {
            protocol: "enso",
            action: "balance",
            args: {
              token: wsrUSD_KATANA,
            },
          },
          // Step 2: Swap wsrUSD to vbUSDC for Yearn compatibility
          {
            protocol: "enso",
            action: "route",
            args: {
              amountIn: { useOutputOfCallAt: 0 },
              tokenIn: wsrUSD_KATANA,
              tokenOut: vbUSDC_KATANA,
              receiver: WALLET_ADDRESS,
            },
          },
          // Step 3: Deposit vbUSDC into Yearn V3 vault
          {
            protocol: "yearn-v3",
            action: "deposit",
            args: {
              amountIn: { useOutputOfCallAt: 1 },
              tokenIn: vbUSDC_KATANA,
              receiver: WALLET_ADDRESS,
              primaryAddress: yvvbUSDC_KATANA,
            },
          },
        ],
      },
    },
  ]
);
Important Considerations
  • Yearn vault strategies automatically optimize yield through multiple DeFi protocols on Katana
  • Bridge operations execute sequentially - Katana operations only proceed after successful Ethereum minting
  • LayerZero bridge fees apply for transfers between Ethereum and Katana
  • Vault deposit generates yvvbUSDC tokens representing your share of the yield-bearing position
  • Gas costs for both chains are paid from the originating Ethereum transaction

Updated