Across is now live on BNB Smart Chain!
Bridge Now!
Across Documentation
V3 Developer Docs
V3 Developer Docs
  • 👋Introduction
    • Welcome to Across
    • What is Across?
    • Technical FAQ
    • Migration Guides
      • Migration from V2 to V3
      • Migration to CCTP
        • Migration Guide for Relayers
        • Migration Guide for API Users
      • Migration Guide for Non-EVM and Prefills
        • Breaking Changes for Indexers
        • Breaking Changes for API Users
        • Breaking Changes for Relayers
        • Testnet Environment for Migration
      • Solana Migration Guide
      • BNB Smart Chain Migration Guide
  • 🌟EXCLUSIVE
    • Integrate BNB Smart Chain
  • 🔗Use Cases
    • Instant Bridging in your Application
      • Bridge Integration Guide
      • Multichain Bridge UI Guide
      • Single Chain Bridge UI Guide
    • Embedded Crosschain Actions
      • Crosschain Actions Integration Guide
        • Using the Generic Multicaller Handler Contract
        • Using a Custom Handler Contract
      • Crosschain Actions UI Guide
    • Settle Crosschain Intents
    • ERC-7683 in Production
  • 🧠Concepts
    • What are Crosschain Intents?
    • Intents Architecture in Across
    • Intent Lifecycle in Across
    • Canonical Asset Maximalism
  • 🛠️Reference
    • API Reference
    • App SDK Reference
    • Contracts
      • Aleph Zero
      • Arbitrum
      • Base
      • BNB Smart Chain
      • Blast
      • Ethereum
      • Linea
      • Ink
      • Lens
      • Lisk
      • Mode
      • Optimism
      • Polygon
      • Redstone
      • Scroll
      • Soneium
      • Unichain
      • World Chain
      • zkSync
      • Zora
    • Selected Contract Functions
    • Supported Chains
    • Fees in the System
    • Actors in the System
    • Security Model and Verification
      • Disputing Root Bundles
      • Validating Root Bundles
    • Tracking Events
  • 🔁Relayers
    • Running a Relayer
    • Relayer Nomination
  • 📚Resources
    • Release Notes
    • Developer Support
    • Bug Bounty
    • Audits
Powered by GitBook
On this page
  • Supported Assets Overview
  • Getting Started
  • Request a Quote
  • Initiating a Deposit (User Intent)
  • Updating Deposits
  • Tracking Deposits
  1. 🌟EXCLUSIVE

Integrate BNB Smart Chain

PreviousBNB Smart Chain Migration GuideNextInstant Bridging in your Application

Last updated 1 day ago

LogoLogo

Products

  • Across Bridge
  • Across+
  • Across Settlement

Socials

  • Discord
  • Twitter
  • Medium
  • Forum

Resources

  • Blog
  • Across Brand Assets
  • Github

Routes

  • Bridge to Unichain
  • Bridge to Arbitrum
  • Bridge to Optimism
  • Bridge to Linea
  • Bridge to Polygon
  • Bridge to Base
  • Bridge to World Chain
  • Bridge to zkSync

Across is expanding support to BNB Smart Chain, enabling seamless bridging assets between Ethereum Mainnet, other supported chains, and BNB Smart Chain.

This guide will contains all technical instructions for using our API to add bridging to and from BNB Smart Chain.

It is a simple two step integration process:

  1. Request quotes from Across API

  2. Use data returned to call functions on Across smart contracts (initiate a deposit)

Supported Assets Overview

With BNB Smart Chain support, Across will enable bridging for:

  • USDC, USDT, ETH → Ethereum Mainnet ↔ Supported L2s ↔ BNB Smart Chain

Expanding support to BNB Smart Chain enhances Across's crosschain interoperability, enabling efficient, cheap and quick bridging across a broader set of EVM-compatible networks.

Before starting the integration, please ensure that you fill this form and get your integrator ID. This will allow us to support you better as you progress towards the production-release and accelerate co-marketing efforts from our side.

Once you fill out the form, we’ll get in touch and provide your integrator ID. In the meantime, you can proceed with the integration by following this guide and simply add the integrator ID once it’s shared with you.


Getting Started

Our focus will be on the /suggested-fees API to support bridging assets to and from BNB Smart Chain. This guide will help you integrate routes to BNB Smart Chain and fetch necessary fees for bridging transactions. Please note the following information as you build your deposit transaction:

  1. BSC_Spokepool: 0x4e8E101924eDE233C13e2D8622DC8aED2872d505

  2. BSC Chain ID: 56


Request a Quote

Initiating a deposit starts with determining the fee necessary to execute the bridging activity.

To do this, you can use the suggested-fees endpoint: app.across.to/api/suggested-fees with the following query parameters:

  • originChainId: chainId where the user's deposit is originating from.

  • destinationChainId: chainId where the user intends to receive their funds.

  • inputToken: the address of the token that the user is depositing on the origin chain.

  • outputToken: the address of the token that the user intends to receive on the destination chain.

  • amount: the raw amount the user is transferring. By raw amount, this means it should be represented exactly as it is in Solidity, meaning 1 USDC would be 1e18 (for BSC) or 1 ETH would be 1e18.

Example for a user transferring 1 ETH from Ethereum to BSC:

https://app.across.to/api/suggested-fees?inputToken=0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2&outputToken=0x2170Ed0880ac9A755fd29B2688956BD959F933F8&destinationChainId=56&originChainId=1&amount=1000000000000000000&skipAmountLimit=true&allowUnmatchedDecimals=true

You can build the deposit transaction completely using the response from the /suggested-fees API. However, please focus on the following fields:

  1. outputAmount: this is the amount of the deposit that the user will need to pay to have it relayed. It is intended to capture all fees, including gas fees, relayer fees, and system fees.

  2. quoteTimestamp: this is the quote timestamp. Specifying this timestamp onchain ensures that the system fees don't shift under the user while the intent is in-flight.

  3. fillDeadline : The recommended deadline (UNIX timestamp in seconds) for the relayer to fill the deposit.

Improve Your UX

To optimize user experience and avoid failed or delayed deposits, use the following output parameters from the Across API response:

  • estimateFillTimeSec – Estimated time (in seconds) for the fill to complete, based on current relayer network conditions.

Liquidity limits provide guidance on what deposit sizes are likely to be filled quickly:

  • limits.maxDepositInstant – Deposits ≤ this value can be filled instantly with current destination-chain liquidity.

  • limits.maxDepositShortDelay – Deposits between maxDepositInstant and this value may experience a short delay (typically <30 minutes).

  • limits.maxDeposit – Upper bound for deposits that can be filled (possibly slowly, up to ~3 hours). Deposits > this value will be rejected.

  • limits.recommendedDepositInstant – Optional soft limit used by some integrations to cap input size for optimal UX.

See the Across API documentation for a complete overview.


Initiating a Deposit (User Intent)

Deposits are initiated by interacting with contracts called SpokePools. There is one SpokePool deployed on each chain supported by Across. Each SpokePool has minor modifications to work with each chain, but maintains the same core interface and implementation. For example, on Ethereum the SpokePool contract is named Ethereum_SpokePool.sol, and on BSC the contract is named BSC_SpokePool.sol.

You can find all supported chains and Spokepool contracts here.

Calling depositV3

Before making the call, you'll need the SpokePool address. This can be retrieved from the GET /suggested-fees response for convenience, but we suggest manually verifying these and hardcoding them per chain in your application for security.

Once you have the SpokePool address, you'll need to approve the SpokePool to spend tokens from the user's EOA or the contract that will be calling the SpokePool . The approval amount must be >= the amount value. If sending ETH, no approval is necessary.

This is the function that needs to be called:

function depositV3(
  address depositor,
  address recipient,
  address inputToken,
  address outputToken,
  uint256 inputAmount,
  uint256 outputAmount,
  uint256 destinationChainId,
  address exclusiveRelayer,
  uint32 quoteTimestamp,
  uint32 fillDeadline,
  uint32 exclusivityDeadline,
  bytes calldata message
) external;

Here is an example of how the parameters could be populated in Javascript:

const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";

// Bridge to the same address on the destination chain.
// Note: If the depositor is not an EOA then the depositor's address
// might not be valid on the destination chain.
const depositor = <USER_ADDRESS>;
const recipient = depositor;

// Test WETH deposit.
const inputToken = response.inputToken.address;

// The 0 address is resolved automatically to the equivalent supported
// token on the the destination chain. Any other input/output token
// combination should be advertised by the Across API available-routes
// endpoint.
const outputToken = response.outputToken.address;

// outputAmount should be taken from the
// Across API suggested-fees response.
const outputAmount = response.outputAmount;

// fillDeadline: A fill deadline of 5 hours. Can be up to
// SpokePool.getCurrentTime() + SpokePool.fillDeadlineBuffer() seconds. You can set that using: `const fillDeadlineBuffer = 18000;`
// or you can simple parse the response from the /suggested-fees API
const fillDeadline = response.fillDeadline;

// timestamp is returned by the Across API suggested-fees endpoint.
// This should be _at least 2_ mainnet blocks behind the current time
// for best service from relayers.
const quoteTimestamp = response.timestamp;

// Exclusive relayer and exclusivity deadline should be taken from the
// Across API suggested-fees response.
const exclusivityDeadline = response.exclusivityDeadline;
const exclusiveRelayer = response.exclusiveRelayer;

// No message will be executed post-fill on the destination chain.
// See `Across+ Integration` for more information.
const message = "0x";

spokePool.depositV3(
  depositor,
  recipient,
  inputToken,
  outputToken,
  inputAmount,
  outputAmount,
  destinationChainId,
  exclusiveRelayer,
  quoteTimestamp,
  fillDeadline,
  exclusivityDeadline,
  message
)

Here is an example of how the parameters could be populated in Solidity:

spokePool.depositV3(
  depositor, // User's address on the origin chain.
  recipient, // Receiving address on the destination chain.
  weth, // inputToken. This is the WETH address on the origin chain.
  address(0), // outputToken: Auto-resolve the destination equivalent token.
  inputAmount,
  outputAmount,
  destinationChainId,
  exclusiveRelayer, // exclusiveRelayer from suggested-fees, or 0x0 to disable
  quoteTimestamp, // suggested-fees timestamp, or block.timestamp - 36
  block.timestamp + spokePool.fillDeadlineBuffer(),
  exclusivityDeadline, // exclusivityDeadline from suggested-fees, or 0 to disable
  "", // message (empty)
);

Append Unique Identifier to CallData

In order to track the origination source for deposits for analytics, debugging and support purposes we request all integrators to append a delimiter of 1dc0de and a unique identifier provided by our team to the deposit transaction call data.

Here is an example of depositV3 call data with 1dc0de delimiter and f001 unique identifier appended.

Function: depositV3(address depositor,address recipient,address inputToken,address outputToken,uint256 inputAmount,uint256 outputAmount,uint256 destinationChainId,address exclusiveRelayer,uint32 quoteTimestamp,uint32 fillDeadline,uint32 exclusivityDeadline,bytes message)

0x7b939232000000000000000000000000c30c7ea910a71ce06ae840868b0c7e47616ba4c9000000000000000000000000c30c7ea910a71ce06ae840868b0c7e47616ba4c9000000000000000000000000833589fcd6edb6e08f4c7c32d4f71b54bda02913000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e5831000000000000000000000000000000000000000000000000000000009502f9000000000000000000000000000000000000000000000000000000000094fd2f84000000000000000000000000000000000000000000000000000000000000a4b100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000066799bfb000000000000000000000000000000000000000000000000000000006679f0f40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000000001dc0def001

Do NOT pass delimiter + identifier to any depositV3 param, including the message param. Only append to call data of the transaction.

Do NOT use f001 identifier in your implementation, request your unique identifier in our shared communication channel or simply fill this form and we will reach out to you.

Please do not use any other identifier other than the one provided to you.


Updating Deposits

Relayer fees are a function of the spread between the outputAmount and inputAmount parameters of a depositV3. If this spread is too low, it may not be profitable for relayers to fill. While a deposit is not filled, the outputAmount can be increased by calling speedUpDepositV3 , which requires a signature from the depositor address. If fees are set according to the above instructions, this functionality should not be needed.


Tracking Deposits

To track the lifecycle of a deposit you can use the GET /deposit/status endpoint with the following parameters:

  • originChainId: The chain Id where the deposit originated from. This needs to be used in conjunction with depositId query parameter.

  • depositId: The deposit id that is emitted from the DepositV3 function call as a V3FundsDeposited event. This needs to be used in conjunction with originChainId query parameter.

  • depositTxHash : The deposit transaction hash when calling depositV3 on the originChain. If you are using this, you do not need the above parameters.

The recommended solution for tracking all Across deposits originating from your integration, for a single user, is to store the user's depositId and originChainId from each transaction originating from your app, and then get the status of each via the above endpoint.

We also provide a deeper explanation to implement your service to track events in Tracking Events.


Congratulations ! You’ve now successfully integrated BNB Smart Chain into your bridge application! If you have any questions, need support, or want to explore advanced use cases, feel free to reach out to us here.

Mass adoption meets mass liquidity