Integrate BNB Smart Chain
Last updated
Last updated
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:
Request quotes from Across API
Use data returned to call functions on Across smart contracts (initiate a deposit)
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.
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:
BSC_Spokepool: 0x4e8E101924eDE233C13e2D8622DC8aED2872d505
BSC Chain ID: 56
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:
You can build the deposit transaction completely using the response from the /suggested-fees API. However, please focus on the following fields:
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.
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.
fillDeadline
: The recommended deadline (UNIX timestamp in seconds) for the relayer to fill the deposit.
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.
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.
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:
Here is an example of how the parameters could be populated in Javascript:
Here is an example of how the parameters could be populated in Solidity:
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.
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.
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.
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.