# Quickstart (/onramp/smart-routing-address/v0_2_1/quickstart)

> For the complete documentation index, see [llms.txt](/llms.txt)



<VersionWarning version="0.2.1" />

A **smart routing address** is a deposit address that accepts funds on any supported chain and delivers them to a destination you choose. Your user can send tokens to it from any chain (even from a CEX), and the funds show up in their wallet on the chain your app runs on.

The API is deliberately small: you call `createSmartRoutingAddress`, then send funds to the address it returns. That's really it.

In this example, we will create a smart routing address that receives funds on Base and transfers them to a wallet on Arbitrum, then send a deposit and check its status.

<div className="fd-steps">
  <div className="fd-step">
    ## Install packages [#install-packages]

    You will be using the following packages:

    <Tabs items="[&#x22;npm&#x22;,&#x22;yarn&#x22;,&#x22;pnpm&#x22;,&#x22;bun&#x22;]">
      <Tab value="npm">
        ```bash
        npm i @zerodev/smart-routing-address@0.2.6 viem
        ```
      </Tab>

      <Tab value="yarn">
        ```bash
        yarn add @zerodev/smart-routing-address@0.2.6 viem
        ```
      </Tab>

      <Tab value="pnpm">
        ```bash
        pnpm add @zerodev/smart-routing-address@0.2.6 viem
        ```
      </Tab>

      <Tab value="bun">
        ```bash
        bun add @zerodev/smart-routing-address@0.2.6 viem
        ```
      </Tab>
    </Tabs>
  </div>

  <div className="fd-step">
    ## Create a project [#create-a-project]

    In v0.2.1 a project is only needed for [fee sponsorship](/onramp/smart-routing-address/v0_2_1/fee-sponsorship). You can skip this step and leave out `config.baseUrl` below.

    * Go to [the ZeroDev dashboard](https://dashboard.zerodev.app/projects/smart-routing-address) and create a project.
    * Copy the project ID and create a `.env` file as follows:

    ```bash
    ZERODEV_PROJECT_ID=<YOUR_PROJECT_ID_FROM_DASHBOARD>
    ```
  </div>

  <div className="fd-step">
    ## Create a smart routing address [#create-a-smart-routing-address]

    Import the SDK and the chains you want to route between:

    ```tsx
    import {
      createSmartRoutingAddress,
      createCall,
      FLEX,
      SMART_ROUTING_ADDRESS_SERVER_URL,
      SMART_ROUTING_ADDRESS_V0_2_1,
    } from "@zerodev/smart-routing-address";
    import { erc20Abi } from "viem";
    import { arbitrum, base } from "viem/chains";
    ```

    Define the calls that run on Arbitrum when funds arrive. Build them with `createCall`, using `FLEX` placeholders for the token address and amount, which aren't known until a deposit lands:

    ```tsx
    // Replace with your own address
    const owner = "0xddED85de258cC7a33A61BC6215DD766E87a97070";

    // Transfer whatever ERC20 arrives, in whatever amount, to `owner`
    const erc20Call = createCall({
      target: FLEX.TOKEN_ADDRESS,
      value: 0n,
      abi: erc20Abi,
      functionName: "transfer",
      args: [owner, FLEX.AMOUNT],
    });

    // Send whatever native amount arrives to `owner`
    const nativeCall = createCall({
      target: owner,
      value: FLEX.NATIVE_AMOUNT,
    });
    ```

    Then create the address. Funds sent to it on Base trigger the matching `actions` on Arbitrum:

    ```tsx
    const { smartRoutingAddress, estimatedFees } = await createSmartRoutingAddress({
      owner,
      destChain: arbitrum,
      // Source tokens (any ERC20 and ETH on Base)
      srcTokens: [
        { tokenType: "ERC20", chain: base },
        { tokenType: "NATIVE", chain: base },
      ],
      // Which calls run on Arbitrum for each token that arrives
      actions: {
        USDC: { action: [erc20Call], fallBack: [] },
        WRAPPED_NATIVE: { action: [erc20Call], fallBack: [] },
        NATIVE: { action: [nativeCall], fallBack: [] },
      },
      slippage: 5000,
      config: {
        version: SMART_ROUTING_ADDRESS_V0_2_1,
        // Only needed for fee sponsorship
        baseUrl: `${SMART_ROUTING_ADDRESS_SERVER_URL}/${process.env.ZERODEV_PROJECT_ID}`,
      },
    });

    console.log("Smart routing address:", smartRoutingAddress);
    ```

    The options are:

    * `owner` is an address that is authorized to recover funds from the smart routing address, in case the smart routing address fails to execute the `actions` for whatever reason. Typically you would set this to your user's EOA wallet, but you could also set it to your own address if you want to recover funds for users.

    * `destChain` is the chain on which the `actions` run. This is presumably the chain that your app runs on.

    * `srcTokens` is a list of tokens that the smart routing address should be able to receive. Only tokens listed in `srcTokens` will be routed to the destination. Other tokens sent to the address will have to be manually recovered by the `owner`. See [Supported Chains](/onramp/smart-routing-address/v0_2_1/supported-chains) for what you can list here.

    * `actions` maps each token type to the calls that run on `destChain` when that token arrives. Every entry needs an `action` list and a `fallBack` list; pass an empty `fallBack` if you don't need one.

    * `slippage` is the *maximum* slippage that the user can expect. `slippage` is an integer, where 1 is equal to 0.01% (so 100 would mean 1% slippage).

    * `config.version` is the **Smart Routing Address version** your address is created against. Pass `SMART_ROUTING_ADDRESS_V0_2_1`. For the latest version, see the [current docs](/onramp/smart-routing-address/quickstart).

    * `config.baseUrl` is only needed for [fee sponsorship](/onramp/smart-routing-address/v0_2_1/fee-sponsorship). Leave it out otherwise.

    * `allowPartialRoutes` is optional. When you list many source chains, one temporarily unavailable route fails the whole call by default. Set it to `true` to create the address anyway and drop the routes that aren't available.

    The return value also includes `estimatedFees`, the estimated fee for each source token deposit.
  </div>

  <div className="fd-step">
    ## Send funds to the address [#send-funds-to-the-address]

    Send any ERC20 or ETH on Base to `smartRoutingAddress`, from any wallet or exchange. No further calls to the SDK are needed. The funds are bridged and the matching `actions` run on Arbitrum automatically.

    <Callout type="warn" title="Only send listed tokens">
      Only tokens on chains listed in `srcTokens` are routed. Anything else sent to the address sits there until the `owner` recovers it through [the portal](https://smart-routing-address.zerodev.app/).
    </Callout>
  </div>

  <div className="fd-step">
    ## Check the deposit status [#check-the-deposit-status]

    Once a deposit lands, you can track it through the bridge and the execution on the destination chain:

    ```tsx
    import { getSmartRoutingAddressStatus } from "@zerodev/smart-routing-address";

    const status = await getSmartRoutingAddressStatus({
      smartRoutingAddress,
    });

    console.log(status.deposits);
    ```

    Each entry in `deposits` includes the source `deposit`, the `bridge` transaction, and the `execution` on the destination chain. See [Fetching Status](/onramp/smart-routing-address/v0_2_1/fetching-status) for the full response shape.

    Congratulations! You just routed funds across chains with a single deposit. Look up `owner` on [Arbiscan](https://arbiscan.io/) to see the funds arrive.
  </div>
</div>

## Next steps [#next-steps]

### FLEX placeholders [#flex-placeholders]

Because the exact token and amount aren't known until a deposit lands, `createCall` lets you leave holes that the router fills in at execution time:

* `FLEX.TOKEN_ADDRESS` — the address of the token that arrived.
* `FLEX.AMOUNT` — the ERC20 amount that arrived (net of fees).
* `FLEX.NATIVE_AMOUNT` — the native amount that arrived.

Use these anywhere a token address or amount is expected — as a `target`, a `value`, or inside `args`.

### Keep going [#keep-going]

* [Sponsor fees](/onramp/smart-routing-address/v0_2_1/fee-sponsorship) so users don't pay for routing.
* Ready to upgrade? Read the [Migration Guide](/onramp/smart-routing-address/migration-guide) to move to v1.
