> ## Documentation Index
> Fetch the complete documentation index at: https://docs.celo.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Bridging CELO from L1 to L2

In this guide, you'll learn how to programmatically bridge CELO from Sepolia to Celo Sepolia using the [viem OP Stack](https://viem.sh/op-stack).

## Steps to Bridge CELO

Before transferring tokens, you must authorize the `OptimismPortalProxy` contract to spend CELO on your behalf. Without this approval, the bridging transaction cannot proceed.

Call the [`depositERC20Transaction`](https://viem.sh/op-stack/actions/depositTransaction#deposittransaction) function on the `OptimismPortalProxy` contract on Sepolia. This function moves CELO tokens from your account to the Celo Sepolia.

## Code Example

The following example demonstrates how to configure a file with all the details you need for interacting with the Celo Sepolia.

<CodeGroup>
  ```js index.js theme={null}
  import { createWalletClient, createPublicClient, http, parseEther } from "viem";
  import { privateKeyToAccount } from "viem/accounts";
  import { celoSepolia, sepolia } from "viem/chains";
  import { getL2TransactionHashes, publicActionsL2 } from "viem/op-stack";

  const CELOL1 = "0xDEd08f6Ec0A57cE6Be62d1876d2CE92AF37eddA0";

  // https://docs.celo.org/cel2/contract-addresses
  const OptimismPortalProxy = "0xB29597c6866c6C2870348f1035335B75eEf79d07";

  const account = privateKeyToAccount(
    "...",
  );

  export const walletClientL1 = createWalletClient({
    account,
    chain: sepolia,
    transport: http(),
  });

  export const publicClientL1 = createPublicClient({
    account,
    chain: sepolia,
    transport: http(),
  });

  export const publicClientL2 = createPublicClient({
    chain: celoSepolia,
    transport: http(),
  }).extend(publicActionsL2());

  async function main() {
    // Approve OptimismPortal to pull CELO on Sepolia
    const approve = await walletClientL1.writeContract({
      address: CELOL1,
      abi: [
        {
          inputs: [
            { name: "spender", type: "address" },
            { name: "amount", type: "uint256" },
          ],
          name: "approve",
          type: "function",
        },
      ],
      functionName: "approve",
      args: [OptimismPortalProxy, parseEther("0.0001")],
    });

    console.log(`Approval TX Hash: ${approve}`);

    let approveReceipt = await publicClientL1.waitForTransactionReceipt({
      hash: approve,
    });
    console.log(`Approve Transaction Receipt: ${approveReceipt}`);

    // Call depositERC20Transaction on OptimismPortal
    const deposit = await walletClientL1.writeContract({
      address: OptimismPortalProxy,
      abi: [
          {
            inputs: [
              {
                name: "_to",
                type: "address",
              },
              {
                name: "mint",
                type: "uint256",
              },
              {
                name: "_value",
                type: "uint256",
              },
              {
                name: "_gasLimit",
                type: "uint64",
              },
              {
                name: "_isCreation",
                type: "bool",
              },
              {
                name: "_data",
                type: "bytes",
              },
            ],
            name: "depositERC20Transaction",
            type: "function",
          },
        ],
        functionName: "depositERC20Transaction",
        args: [
          account.address, // Account where you want to receive CELO on L2
          parseEther("0.0001"), // Amount you are transferring to the Portal
          parseEther("0.0001"), // Amount you want on L2
          100_000, // Amount of L2 gas to purchase by burning gas on L1.
          false, // Whether the transaction is a contract creation
          "", // Data to trigger the recipient with
        ],
    });

    console.log(`Deposit Transaction: ${deposit}`);


    let depositReceipt = await publicClientL1.waitForTransactionReceipt({
      hash: deposit,
    });
    console.log(`Deposit Transaction Receipt: ${depositReceipt}`);

    // Get the L2 transaction hash from the L1 transaction receipt.
    const [l2Hash] = getL2TransactionHashes(depositReceipt);

    // Wait for the L2 transaction to be processed.
    const l2Receipt = await publicClientL2.waitForTransactionReceipt({
      hash: l2Hash,
    });

    console.log(`L2Receipt: ${l2Receipt}`);
  }

  main();
  ```
</CodeGroup>
