Move USDC across chains in a supported EVM testnet flow using Gas Station for deposits and the Forwarding Service for destination minting.

Every chain charges gas in its own token. If you're moving USDC across multiple blockchains, that often means acquiring each chain's native token before you can move stable value on that chain. There's a tension worth noticing: your product deals in stablecoins, but your operations depend on a set of volatile tokens that exist purely to pay for infrastructure.
This post walks through the full round-trip, from depositing USDC into Circle Gateway from multiple source chains, delegating transfer authority to avoid the smart contract account (SCA) signing constraint, and transferring across chains with the Forwarding Service broadcasting the mint on the destination, in the EVM testnet flow shown here without separately acquiring native gas tokens for the participating wallets.
If you're new to Gas Station, we have an earlier blog post, "Abstract Away Gas Tokens and Fees with Circle's Gas Station", which explains the EVM implementation, ERC-4337 mechanics and Paymaster/Policy/Billing components.
The native token tax
Supporting multiple chains means managing multiple native tokens, one per chain, each with its own price feed, its own balance to monitor, and its own acquisition path.
On testnet, this often means faucet hunting. Each chain has its own faucet with its own rate limits, uptime issues, and token quantities. Testnet faucets also vary in availability and distribution. Before you can test a single USDC deposit, you typically need each chain's testnet native token from its respective faucet. The number of prerequisites grows linearly with the number of chains.
On mainnet, the problem is worse. Your treasury must hold volatile native tokens solely to pay gas for moving stable assets. Every native token balance is an exposure because its value fluctuates with the market, it needs monitoring and topping up, and it introduces accounting complexity that has nothing to do with your actual product. Your core product moves stablecoins, but your cost structure includes a portfolio of volatile tokens you need to actively manage.
For a single chain, this is manageable overhead. Across multiple chains, it becomes operational drag.
Three paths to USDC-only operations
There are three ways to reduce or abstract away the need to manage native gas tokens, each suited to different architectures and cost models.
Path A: Arc, where the problem doesn't exist
Arc features stablecoins as gas, starting with USDC. There is no separate native gas token to acquire or manage. When you deposit USDC into Gateway on Arc Testnet, the gas fee is denominated in USDC, the same asset you're depositing. This means the fee asset and the deposited asset are both USDC, which can simplify balance management relative to flows that require a separate gas token. For a deeper look at how Arc's fee model works, see "How Gas Works on Arc".
This can be the most straightforward path, but it only applies when your source chain is Arc. For other chains in a multichain setup, you need one of the approaches below.
Path B: Gas Station, where the developer sponsors gas
Gas Station covers transaction fees on behalf of your wallets, similar to how a platform might absorb payment processing fees so the end user doesn't see them. In supported Gas Station flows, the wallets do not need to hold native tokens to pay network fees directly; instead, the developer is billed in fiat via credit card (with a 5% processing fee). This requires Smart Contract Account (SCA) wallets, which Circle Wallets can create on supported chains.
Gas Station is a feature of Wallets, available on a growing set of chains supported by Circle Wallets. In the testnet setup used for this post, Gas Station did not require additional policy configuration. You enable it, create SCA wallets, and qualifying transactions are sponsored as part of that setup.
For a deep dive into the EVM implementation, see the previous Gas Station post.
Path C: Circle Paymaster, where the user pays gas in USDC
Circle Paymaster takes a different approach. Instead of the developer absorbing gas costs, the user pays, but in USDC, not in native tokens. It's a permissionless smart contract designed for ERC-4337-compatible wallet flows.
The surcharge is 10% of the gas fee, paid by the end user in USDC. This can be a better fit when you don't want to absorb gas costs as a business expense, but still want to shield users from needing native tokens.
The full round-trip, zero native tokens
This is where the pieces converge into a practical outcome that neither Gas Station nor Gateway demonstrates in isolation: deposit USDC from multiple chains, transfer it across chains, and mint it on the destination, while abstracting away native gas management in the EVM testnet setup shown here.
The setup: the testnet chains used in this walkthrough where both Gateway and Gas Station were supported, each with a developer-controlled SCA wallet holding testnet USDC from the Circle faucet. Gas Station is enabled. In this setup, we did not need to separately source native tokens for the participating wallets.
The flow
On each chain, the deposit into Gateway is a two-transaction sequence: an ERC-20 approve granting the Gateway Wallet contract permission to spend USDC, followed by a deposit(address, uint256) call on the contract itself.
With Gas Station enabled, the wallet does not need to hold native gas tokens to submit either transaction. The SCA wallet submits the transactions, Gas Station's paymaster sponsors the gas, and the wallet's native token balance can stay at zero throughout.
First, create SCA wallets across the target chains. By passing a shared refId, Wallets derives the same address on every EVM chain so the depositor identity is consistent across all of them.
import { initiateDeveloperControlledWalletsClient } from "@circle-fin/developer-controlled-wallets";
const client = initiateDeveloperControlledWalletsClient({
apiKey: "<YOUR_API_KEY>",
entitySecret: "<YOUR_ENTITY_SECRET>",
});
// Create a wallet set
const walletSetResponse = await client.createWalletSet({
name: "Gateway Wallet Set",
});
// Create wallets on supported blockchains
const walletsResponse = await client.createWallets({
blockchains: ["ETH-SEPOLIA", "BASE-SEPOLIA", "AVAX-FUJI", "ARC-TESTNET", "ARB-SEPOLIA", "UNI-SEPOLIA", "MATIC-AMOY", "OP-SEPOLIA"],
count: 1,
accountType: "SCA",
walletSetId: walletSetResponse.data?.walletSet?.id ?? "",
metadata: [{
refId: "sca-depositor"
}]
});
Then, for each chain, approve the Gateway Wallet contract to spend USDC and deposit:
const GATEWAY_WALLET = "0x0077777d7EBA4688BDeF3E311b846F25870A19B9";
// Approve Gateway Wallet to spend USDC
const approveTx = await client.createContractExecutionTransaction({
walletAddress: depositorAddress,
blockchain: "ETH-SEPOLIA", // repeat for each chain
contractAddress: usdcAddress,
abiFunctionSignature: "approve(address,uint256)",
abiParameters: [GATEWAY_WALLET, depositAmount],
fee: { type: "level", config: { feeLevel: "MEDIUM" } },
});
// Deposit USDC into Gateway
const depositTx = await client.createContractExecutionTransaction({
walletAddress: depositorAddress,
blockchain: "ETH-SEPOLIA",
contractAddress: GATEWAY_WALLET,
abiFunctionSignature: "deposit(address,uint256)",
abiParameters: [usdcAddress, depositAmount],
fee: { type: "level", config: { feeLevel: "MEDIUM" } },
});
Repeat this across each participating chain. In this example, each wallet was funded with USDC only. In the tested EVM flows, the approve and deposit transactions were sponsored by Gas Station (or paid in USDC natively on Arc Testnet).
After deposits complete and finalize on each chain, the depositor's Gateway balance reflects USDC from all sources:
const balances = await fetch("https://gateway-api-testnet.circle.com/v1/balances", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
token: "USDC",
sources: domainIds.map((domain) => ({ domain, depositor: depositorAddress })),
}),
});
The wallet balances tell the story: USDC balances decreased by the deposited amounts, and native token balances can remain at zero for the participating wallets in this flow. You now have a unified Gateway balance that can be transferred to supported destination chains, and the participating wallets did not need to be separately funded with native gas tokens to get here.
Setting up delegation for transfers
Depositing into Gateway from an SCA wallet works directly, but transferring out does not. Burn intents require an EIP-712 signature, and Gateway does not accept EIP-1271 (smart contract) signatures. To transfer from the unified balance, you need to assign an EOA delegate, which is a separate wallet capable of signing on the SCA's behalf.
A practical simplification: create a single EOA wallet with Wallets using the EVM-TESTNET blockchain type. This gives you one address that can sign for any EVM chain, so you don't need to create a separate companion EOA on every chain. Register that one address as the delegate everywhere.
Call addDelegate on the Gateway Wallet contract for each chain where the SCA holds deposits. This transaction is also sponsored by Gas Station, without requiring the SCA wallet to hold native gas tokens in this setup:
const delegateTx = await client.createContractExecutionTransaction({
walletAddress: depositorAddress, // SCA wallet
blockchain: "ETH-SEPOLIA", // repeat for each chain
contractAddress: GATEWAY_WALLET,
abiFunctionSignature: "addDelegate(address,address)",
abiParameters: [usdcAddress, delegateAddress],
fee: { type: "level", config: { feeLevel: "MEDIUM" } },
});
After this, the delegate can sign burn intents for the SCA's deposited USDC on that chain. Without delegation, the only exit path is the 7-day trustless withdrawal.
Transferring across chains with the Forwarding Service
With deposits funded and delegation in place, the final piece is moving USDC from the unified balance to a destination chain without separately funding the participating wallets with native gas tokens.
The transfer is entirely offchain until the mint. The delegate constructs a burn intent specifying how much to move and where, signs it as EIP-712 typed data, and submits to the Gateway API. With the Forwarding Service enabled, the Forwarding Service API handles the destination-side broadcasting step, so you do not need to operate a separate destination wallet flow for this example.
The key concept in the burn intent is the separation of ownership from signing: the SCA wallet owns the funds (sourceDepositor), while the EOA delegate authorizes the transfer (sourceSigner).
// Simplified burn intent (not full code)
const burnIntent = createBurnIntent({
sourceChain: "arc",
depositorAddress: SCA_ADDRESS, // SCA wallet (owns funds)
signerAddress: DELEGATE_ADDRESS, // EOA delegate (signs)
recipientAddress: SCA_ADDRESS, // can be any address
});
Before signing, estimate the forwarding fees. The estimate endpoint returns the maxFee and maxBlockHeight to include in the signed burn intent:
const estimate = await fetch(
"https://gateway-api-testnet.circle.com/v1/estimate?enableForwarder=true",
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify([{ spec: paddedSpec }]),
},
);
Sign with the delegate wallet. The signTypedData call is offchain:
const sigResp = await client.signTypedData({
walletAddress: DELEGATE_ADDRESS,
blockchain: "EVM-TESTNET",
data: JSON.stringify(typedData),
});
Submit the signed burn intent to the Gateway API with forwarding enabled:
const response = await fetch(
"https://gateway-api-testnet.circle.com/v1/transfer?enableForwarder=true",
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify([{ burnIntent: typedData.message, signature: sigResp.data.signature }]),
},
);
const { transferId } = await response.json();
The response returns a transferId rather than an attestation. Poll GET /v1/transfer/{transferId} until the status reaches confirmed, then the Forwarding Service handles the broadcasting on the destination chain. The forwarding fee is deducted from the USDC amount, so the recipient receives the transfer value minus fees. In this example, the participating wallets did not need to hold native gas tokens at any point in the flow.
If you want to minimize USDC fees and already have an SCA wallet on the destination chain, you can skip the Forwarding Service and call gatewayMint from that SCA wallet directly. Gas Station sponsors the onchain mint transaction just like it sponsors the deposits. This can reduce USDC-denominated fees relative to using the Forwarding Service, because you avoid the forwarding fee and instead broadcast the destination-side mint yourself. The tradeoff is that you need to maintain an SCA wallet and broadcast the mint transaction yourself on the destination chain.
The result
In the EVM testnet round-trip shown here, the participating wallets completed the flow without holding native gas tokens. USDC was deposited from multiple source chains into a unified Gateway balance, transferred across chains via the Forwarding Service, and minted on the destination without separately funding those wallets with native gas tokens. The costs in this flow are Gateway's base and transfer fees, plus the forwarding fee if using the Forwarding Service, all denominated in USDC and deducted from the transfer amount.
When to use which path
Building natively on Arc → USDC as gas. Gas is already denominated in USDC, so there's less to configure.
Developer-controlled backend wallets → Gas Station. Developers absorb gas as a business cost and supported wallet flows do not require the wallet to hold native gas tokens directly.
User-facing app, developer pays → Gas Station. Users don't see gas fees, which simplifies the experience.
User-facing app, user pays → Paymaster. The developer doesn't absorb the cost, the user pays in USDC instead of native tokens.
Multichain treasury automation → Gas Station Gateway. A unified Gateway balance with less need to manage native gas token balances across chains.
These paths can be combined. A multichain app might use Arc's native USDC gas for Arc-originated transactions, Gas Station for developer-controlled operations on other chains, and Paymaster for user-initiated actions where the user bears the cost.
What this unlocks
Removing native tokens from the operational path changes what's practical to build:
AI agents that operate across chains with only USDC. An autonomous agent managing a multichain treasury may not need a native token balance on each participating chain, depending on how the flow is implemented. It holds USDC, deposits into Gateway from wherever USDC arrives, transfers to wherever it's needed, and the Forwarding Service handles the broadcasting without needing a human to acquire gas tokens. Using the Forwarding Service can also reduce the amount of destination-side transaction broadcasting you need to operate directly.
Treasury consolidation with less operational intervention. A scheduled process can sweep USDC from multiple chains into Gateway and redistribute to destination chains without the same level of native token balance monitoring and top-ups that these flows often require otherwise.
Onboarding with fewer funding prerequisites. A new user's first meaningful action may not require acquiring a native token first in supported Gas Station flows. Fund the wallet with USDC, and the full lifecycle, from account deployment, deposits, transfers, and mints, can be covered by Gas Station and the Forwarding Service in the setup shown here.
Development and testing with fewer faucet dependencies. On testnet, the Circle faucet provides USDC across supported chains. With Gas Station handling gas and the Forwarding Service handling destination broadcasting in this setup, that can reduce the number of faucets you need to rely on during testing.
The common thread is simplification. Each of these scenarios can otherwise require managing native token balances across every chain you touch, including monitoring levels, triggering top-ups, or handling failures when balances run dry. With Gas Station, Gateway, and the Forwarding Service working together, the operational focus shifts closer to a single asset, USDC. In practice, that can simplify funding and balance management compared with flows that require separate native gas tokens on each chain.
Get started
- Gateway documentation
- Gateway Forwarding Service
- Gas Station documentation
- Circle Paymaster documentation
- Circle faucet
- Gateway smart contract addresses
Circle Technology Services, LLC (“CTS”) is a software provider and does not provide regulated financial or advisory services. You are solely responsible for services you provide to users, including obtaining any necessary licenses or approvals and otherwise complying with applicable laws. For additional details, please refer to the Circle Developer terms of service.
USDC is issued by regulated affiliates of Circle. See Circle’s list of regulatory authorizations.
Arc testnet provided by Circle Technology Services, LLC, a software provider. Not a financial or advisory service. Not reviewed or approved by NYDFS. Users responsible for their own compliance. See arc.network for more.
Circle Wallets are provided by Circle Technology Services, LLC (“CTS”). CTS is a software provider and does not provide regulated financial or advisory services. You are solely responsible for services you provide to users, including obtaining any necessary licenses or approvals and otherwise complying with applicable laws. For additional details, refer to the Circle Developer Terms of Service.




