Skip to main content
This workflow demonstrates complex multi-hop crosschain operations where origin chain assets bridge to the minting chain, create new tokens, then return for yield deployment. The pattern shows how to leverage centralized minting while maintaining yield positions on preferred chains. Route Mechanics: This advanced bundle orchestrates a complete crosschain yield strategy through multiple atomic transactions:
  • Bridge USDCe from Berachain to Ethereum using Stargate protocol
  • Check USDCe balance on Ethereum after successful bridge completion
  • Mint rUSD using the bridged USDCe through Reservoir’s minting contract
  • Bridge newly minted rUSD back to Berachain via Stargate bridge
  • Check rUSD balance on Berachain after bridging
  • Deposit rUSD into Euler V2 vault for automated yield generation
mintOnBeraDepositOnMainnet.ts
const BERACHAIN_ID = 80094;
const ETHEREUM_ID = 1;

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

// Token addresses
const USDCE_BERACHAIN = "0x549943e04f40284185054145c6E4e9568C1D3241";
const USDC_ETHEREUM = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48";
const RUSD_ETHEREUM = "0x09D4214C03D01F49544C0448DBE3A27f768F2b34";
const RUSD_BERACHAIN = "0x09D4214C03D01F49544C0448DBE3A27f768F2b34";

// Protocol addresses
const RESERVOIR_MINTING_CONTRACT =
  "0x4809010926aec940b550D34a46A52739f996D75D";

const EULER_VAULT_E_RUSD_BERACHAIN =
  "0xB8064453B25a91D7a4e8b7e7883A817D5742dE34"; // Euler vault srUSD/USDe on Berachain (need actual address)

const srUSD = "0x5475611dffb8ef4d697ae39df9395513b6e947d7";

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

const usdcBeraToEthPools = await client.getLayerZeroPool({
  chainId: BERACHAIN_ID,
  token: USDCE_BERACHAIN,
  destinationChainId: ETHEREUM_ID + "",
});

const rusdEthToBeraPools = await client.getLayerZeroPool({
  chainId: ETHEREUM_ID,
  token: RUSD_ETHEREUM,
  destinationChainId: BERACHAIN_ID + "",
});

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

const bundle = await client.getBundleData(
  {
    chainId: BERACHAIN_ID,
    fromAddress: WALLET_ADDRESS,
    spender: WALLET_ADDRESS,
    routingStrategy: "router",
  },
  [
    {
      protocol: "stargate",
      action: "bridge",
      args: {
        primaryAddress: usdcBeraToEthPools[0].pool,
        destinationChainId: ETHEREUM_ID,
        tokenIn: USDCE_BERACHAIN,
        amountIn: parseUnits("1000", 6).toString(), // 1000 USDC
        receiver: WALLET_ADDRESS,
        callback: [
          // Step 1: Check USDCe balance on Ethereum after bridge
          {
            protocol: "enso",
            action: "balance",
            args: {
              token: USDC_ETHEREUM,
            },
          },
          // Step 2: Mint rUSD using bridged USDCe on Ethereum
          {
            protocol: "reservoir",
            action: "deposit",
            args: {
              primaryAddress: RESERVOIR_MINTING_CONTRACT,
              tokenIn: USDC_ETHEREUM,
              tokenOut: RUSD_ETHEREUM,
              amountIn: { useOutputOfCallAt: 0 }, // Use USDCe from balance check
              receiver: WALLET_ADDRESS,
            },
          },
          // Step 3: Bridge newly minted rUSD back to Berachain
          {
            protocol: "stargate",
            action: "bridge",
            args: {
              primaryAddress: rusdEthToBeraPools[0].pool,
              destinationChainId: BERACHAIN_ID,
              tokenIn: RUSD_ETHEREUM,
              amountIn: { useOutputOfCallAt: 1 }, // Use rUSD from minting
              receiver: WALLET_ADDRESS,
              // Callback executes on Berachain after rUSD arrives
              callback: [
                // Step 1: Check rUSD balance on Berachain
                {
                  protocol: "enso",
                  action: "balance",
                  args: {
                    token: RUSD_BERACHAIN,
                  },
                },
                // Step 2: Route rUSD to srUSD
                {
                  protocol: "enso",
                  action: "route",
                  args: {
                    tokenIn: RUSD_BERACHAIN,
                    tokenOut: srUSD,
                    amountIn: { useOutputOfCallAt: 0 },
                  },
                },
                // Step 3: deposit into Euler v2 srUSD vault
                {
                  protocol: "euler-v2",
                  action: "deposit",
                  args: {
                    primaryAddress: EULER_VAULT_E_RUSD_BERACHAIN,
                    tokenIn: srUSD,
                    tokenOut: EULER_VAULT_E_RUSD_BERACHAIN,
                    amountIn: [{ useOutputOfCallAt: 1 }], // Use e-rUSD from balance check
                    receiver: WALLET_ADDRESS,
                  },
                },
              ],
            },
          },
        ],
      },
    },
  ]
);
Important Considerations
  • All crosschain operations execute atomically - if any step fails, the entire transaction reverts and funds are safely returned
  • Gas costs for all destination chains are calculated and paid upfront using LayerZero’s native drop feature
  • Bridge fees and slippage may cause slight variations in final amounts received

Updated