Bridge Integration Guide
This guide contains technical instructions for using our API to provide bridge quotes to your users via bridge experience alongside your application. 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)
Request a Quote
The process for initiating a deposit begins with determining the fee that needs to be paid to the relayer. 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 originatingdestinationChainId
: chainId where the user intends to receive their fundstoken
: the address of the token that the user is depositing on the origin chainamount
: 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 1e6 or 1 ETH would be 1e18.
Example for a user transferring 1000 USDC from Ethereum to Optimism:
There are two elements of the response that you'll need to create the deposit:
totalRelayFee.total
: 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.timestamp
: 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.
To determine how long a fill is expected to take and to ensure that Across can process a deposit of a given size, you'll want to refer the following elements of the response:
fillSpeedType
: one ofinstant
,shortDelay
orslow
corresponding to an instant fill (within seconds), short delay (within 5-15 minutes) or slow (~3 hours)estimateFillTimeSec
= the estimated fill time, for the specified route and asset, in seconds
The above values depend on the amount
in the request relative to the following limit elements of the response:
maxDepositInstant
: if the user's amount is less than or equal to this amount, there is known to be enough relayer liquidity on the destination chain to fill them instantly, within secondsmaxDepositShortDelay
: if the user's deposit amount is larger than maxDepositInstant, and less than or equal to this amount, there is known to be enough relayer liquidity that can be moved to the destination chain to fill the user within 30 minutesmaxDeposit
: if the user's deposit amount is larger than maxDepositShortDelay, and less than or equal to this amount, there is enough liquidity in Across to fill them via a slow fill, which could take up to 3 hours. In most casesmaxDeposit
will be equal tomaxDepositShortDelay
to reduce the likelihood of slow fills. If the user's deposit amount is larger than this, Across cannot fulfill the user's intentreccommendedDepositInstant
: this is used for certain integrations to limit the input size, and is currently hardcoded to 2 ETH/WETH and 5,000 USDC
You can find details on the Across API here.
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 Optimism the contract is named Optimism_SpokePool.sol
.
Calling depositV3
Before making the call, you'll need the SpokePool
address. This can be retrieved from the suggested-fees response for convenience, but we suggest manually verifying these and hardcoding them per chain in your application for security. You can find the addresses here.
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.
The deposit call can come from an intermediary contract or directly from the user's EOA. This is the function that needs to be called:
Here is an example of how the parameters could be populated in Javascript:
and in Solidity (see also the Javascript descriptions above):
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, see below on how to request your unique ID.
Request your unique identifier in our shared communication channel (TG, Slack, etc), if already set up, or reach out to [email protected]. 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 app.across.to/api/deposit/status endpoint with the following parameters:
originChainId
: chain Id where the deposit originated fromdepositId
: The deposit id that is emitted from theDepositV3
function call as aV3FundsDeposited
event
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.
Last updated