Across Docs

Gas top-up

Deliver some of the destination chain's native gas token along with the transfer, so the recipient can transact right away.

A recipient who arrives on a new chain holding only USDC cannot pay for their next transaction. Add gasTopUp to the quote and Across also delivers a fixed amount of the destination chain's native token, ETH on Base for example, to the same recipient.

How it works

  1. Check that the route supports a top-up, and the most you can request.
  2. Add gasTopUp to the quote.
  3. Execute the quote as usual.
  4. Confirm the gas arrived on the transfer.

Check the route

Call GET /v1/capabilities with all four sides anchored, and read capabilities.gasTopUp.

1-check.ts
const BASE_URL = "https://api.across.to";
const API_KEY = process.env.ACROSS_API_KEY;

const res = await fetch(
  `${BASE_URL}/v1/capabilities` +
    "?originChainId=42161&originToken=0xaf88d065e77c8cC2239327C5EDb3A432268e5831" +
    "&destinationChainId=8453&destinationToken=0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913" +
    "&include=chains",
  { headers: { Authorization: `Bearer ${API_KEY}` } },
);

const { capabilities } = await res.json();
const gas = capabilities?.gasTopUp;
"gasTopUp": {
  "supported": true,
  "token": { "kind": "native", "chainId": 8453, "address": "0x0000000000000000000000000000000000000000", "symbol": "ETH", "decimals": 18 },
  "limits": {
    "max": { "amount": "2183978334934917" },
    "validUntil": "2026-11-03T21:07:02.375Z"
  }
}
FieldMeaning
supportedWhether this pair can carry a top-up
tokenThe destination's native token, with its decimals
limits.max.amountThe most you can request right now, in that token's base units
limits.validUntilWhen that maximum goes stale

The block is absent until all four sides resolve. A missing limits means no current maximum is known, not that there is none. The quote checks the amount again either way.

The maximum is a USD limit per transfer, converted at the current native price: currently $25 on Ethereum and $5 on other destinations.

Quote with a top-up

Add gasTopUp.amount to your usual quote body, in native base units.

2-quote.ts
const res = await fetch(`${BASE_URL}/v1/quotes`, {
  method: "POST",
  headers: {
    Authorization: `Bearer ${API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    origin: {
      token: { chainId: 42161, address: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831" },
      amount: "10000000", // 10 USDC
      depositor: "0xYourWalletAddress",
    },
    destination: {
      token: { chainId: 8453, address: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913" },
      recipient: "0xYourWalletAddress",
    },
    gasTopUp: { amount: "500000000000000" }, // 0.0005 ETH
  }),
});

const quote = await res.json();
// quote.gasTopUp → { token: { symbol: "ETH", decimals: 18, ... }, amount: "500000000000000" }

The top-up goes to destination.recipient; you cannot pick another token or address. "0" is the same as leaving gasTopUp out.

The transfer pays for the top-up at the current native price:

  • exact_input: it comes out of the output. destination.amount is lower than without a top-up, and destination.grossAmount is already net of it.
  • exact_output and min_output: the output is unchanged and origin.amount goes up instead.

It is not a fee. It is not part of fee, and it does not count against maxFee or subsidy. Your app fee is still charged on the full input.

Show it as something the user receives. List the top-up next to the output ("+ 0.0005 ETH for gas on Base"), not under fees or total cost.

Execute as usual

Follow the quote's nextActions exactly as you would without a top-up. Nothing extra is signed or sent.

Confirm the gas arrived

GET /v1/transfers/{orderId} carries two gasTopUp objects, each with a token and an amount:

FieldMeaning
quoted.gasTopUpThe amount the quote promised
gasTopUp (top level)The amount proven delivered on chain

If quoted.gasTopUp is there and the top-level gasTopUp is not, the payment is not confirmed yet, or the transfer refunded without gas. Wait for status.finalized: true before treating the outcome as final. An Across refund on the destination can pay the gas to the refund recipient; CCTP and OFT refunds return only the bridged token.

Where it works

  • Cross-chain routes between EVM chains, on Across, CCTP and OFT.
  • From Solana to EVM chains.
  • Wrapped native outputs, such as WETH, qualify. Native outputs, such as ETH, do not.
  • With destinationActions: the top-up is sent before the steps run, and onFailure.recipient must be destination.recipient.

Not available on same-chain swaps, or on Solana (coming soon), HyperCore, Lighter and Tron destinations. Rely on capabilities.gasTopUp for a specific pair rather than this list.

Errors

All carry param: "gasTopUp.amount".

ErrorMeaning
400 request.unsupported_paramThe route cannot carry a top-up
400 policy.amount_out_of_rangeAbove the destination's USD limit
400 request.invalid_fieldThe transfer is too small to pay for the top-up

On this page