Gateway

Gateway Technical Guide

Circle Gateway consists of two smart contracts (each deployed on multiple chains), as well as an offchain system. Users deposit USDC into Gateway Wallet contracts on any supported source chain. Once their deposits are finalized, they can instantly transfer their USDC to a destination chain through an API call, followed by a contract call to the Gateway Minter on the destination chain. The contracts, together with the offchain system, ensure the integrity of the USDC supply and prevent double-spending.

Compared to CCTP, Gateway allows users to front-load the finalization wait time rather than requiring finality in the middle of a transfer flow. This enables users to use all of their USDC instantly on any chain (even in amounts exceeding the balance held on any single chain), without needing to decide beforehand what amount or destination is be needed. As such, it is optimized for use-cases requiring capital efficiency, low latency, and chain abstraction.

The wallet contract accepts deposits from users via direct transfer, EIP-2612 permit, or ERC-3009 authorization. It is deployed to multiple chains so users can deposit from whatever source chain they hold USDC on. The contract is non-custodial, meaning users always have full control over their USDC and Circle cannot transfer or burn any USDC without explicit user authorization. Once USDC is deposited and the deposit events have been finalized onchain, they are available to be used crosschain.

In order to preserve the non-custodial nature of the USDC held in the Gateway Wallet contract, there is a trustless withdrawal mechanism that may be used in the unlikely event that Circle's APIs are down for an extended period or service is otherwise unavailable. To withdraw USDC completely onchain with no API interaction, users must first initiate a withdrawal with a transaction, wait for a 7-day withdrawal delay period, and then the user may complete the withdrawal and receive the USDC. This delay is what allows the Gateway System to safely issue attestations to instantly transfer USDC to other chains, since it guarantees that there is sufficient time to submit the corresponding burn transaction.

The minter contract accepts attestations signed by the Gateway System and mints USDC to the specified destination. It is also deployed to multiple chains, including chains that may not yet support the wallet contract.

Circle runs an offchain, automated system that serves an API for user interaction, observes onchain events, and ensures that every mint on a destination chain corresponds 1:1 with a burn on each source chain.

At the center of the system is an offchain ledger that represents the USDC balances that are deposited and are available for use in instant transfers. These balances are tracked for every combination of chain, token, and address. They can be thought of as eventually consistent with onchain state, where safety is ensured by mechanisms built into the wallet contract.

The following table describes the main inputs to the Gateway System, along with what it does in response to each.

InputResponse
Deposit eventIncrement balance
Transfer request (attestation issued)Decrement balance
AttestationUsed eventSubmit burn intents to source chains
Attestation expires unusedIncrement balance
WithdrawInitiated eventDecrement balance

All onchain events are only observed as they are finalized. See Required block confirmations for the details on what is considered finalized on each supported chain.

The contracts and API share a set of primitives that are used to represent transfers consistently, both when interacting with the API and as inputs to the smart contracts. There is also a byte encoding for each that is used across chains. See the source code of the EVM contracts for details about widths, offsets, and type markers.

A transfer specification describes everything about a transfer from one domain to another. It is embedded in the other two primitives, and its keccak256 hash is used as a crosschain identifier as well as replay protection.

TransferSpec

FieldDescription
versionThe protocol version, used for forward compatibility. Always set to 1.
sourceDomainThe domain of the wallet contract from which this transfer came
destinationDomainThe domain of the minter contract from which this transfer is valid
sourceContractThe address of the wallet contract on the source domain
destinationContractThe address of the minter contract on the destination domain
sourceTokenThe token address on the source domain
destinationTokenThe token address on the destination domain
sourceDepositorThe address to debit within the wallet contract on the source domain
destinationRecipientThe address to receive the USDC on the destination domain
sourceSignerThe signer who signed for the transfer (may be the same as sourceDepositor)
destinationCallerThe address of the caller who may use the attestation (0 for any caller)
valueThe amount to be transferred
saltAn arbitrary value that can make the transfer spec hash unique
hookDataArbitrary bytes that may be used for onchain composition

A burn intent is constructed and signed by the user, and provided to the Gateway API during a transfer request. This is used to authenticate the user (since it must be signed by the address specified in the sourceSigner field of the transfer spec) as well as to declare the parameters of the desired transfer.

BurnIntent

FieldDescription
maxBlockHeightThe expiration block height on the source chain
maxFeeThe maximum fee that may be collected by Circle
specThe transfer specification describing the desired transfer

This user-signed payload is what Gateway System uses to prove to the wallet contract on the source chain that the user intended to make the specified transfer. Without this user signature, Circle is unable to unilaterally burn or transfer user assets from the wallet contract to complete the transfer loop. To further cement the non-custodial nature of the wallet contract, burn intents expire so that the Gateway System does not hold “active” intents for long.

At the time of the transfer request, the Gateway System verifies that the user's signature is valid, that the expiry block is sufficiently far in the future (at least the wallet's withdrawalDelay from the current block), and that the fee is sufficient to cover both the gas for the burn transaction and the transfer fee.

If multiple burn intents share a common sourceSigner and the relevant chains all share the same signature scheme (such as multiple EVM chains), burn intents may be packed together into a burn intent set and signed as a single payload:

BurnIntentSet

FieldDescription
intentsAn array of burn intents describing multiple transfers

For EVM chains, this structure is signed as EIP-712 typed data. For other chains, it is signed in its byte-encoded form. Because the Gateway System needs to statically verify the signature offchain and guarantee that the signature is still be valid at the time of the burn transaction, only EOA signatures are accepted. To use Gateway with SCAs, the SCA must add an EOA as a delegate that may sign transfer requests (see below for more details).

An attestation is constructed and signed by the Gateway System in response to a transfer request. It proves to the minter contract that at the time of the transfer request, the user had a sufficient balance in the wallet contracts and all other details of the transfer were valid, so the mint is safe to perform.

Attestation

FieldDescription
maxBlockHeightThe expiration block height on the destination chain
specThe transfer specification describing the desired transfer

The transfer specification contained in an attestation is identical to what was signed by the user. Because of this, its keccak256 hash is emitted during the mint transaction and the same hash is be emitted during the corresponding burn transaction. This allows for crosschain traceability and reconciles the 1:1 relationship between mints and burns in the system.

When a transfer involves multiple source domains (such as when the user passes a burn intent set or multiple standalone burn intents), the Gateway System constructs and signs an attestation set:

AttestationSet

FieldDescription
attestationsAn array of attestations describing multiple transfers

While events are emitted for each attestation contained in a set, the entire transaction is atomic and only one mint (of the total value of all contained attestations) happens during the transaction.

The Gateway System supports the following key operations.

In order to deposit USDC into the Gateway System, users may choose between several onchain deposit methods:

MethodDescription
depositDeposit to the contract after granting an allowance for the token
depositForSame as deposit, but credit the USDC to another depositor's balance
depositWithPermitDeposit using a signed EIP-2612 permit (credited to the signer)
depositWithAuthorizationDeposit using a signed ERC-3009 authorization (credited to the signer)

It's important to note that before deposited USDC shows up in the Gateway System and may be used for transfers, the deposit transactions must be finalized onchain. See Required block confirmations for more details about what is considered finalized on each supported chain.

Use the /v1/balances endpoint of the API to check the latest available balance recorded by the Gateway System. These balances are what is available to be instantly transferred using a transfer request.

First, construct a burn intent or burn intent set describing the desired transfer. Sign it with the address that owns the USDC or is an authorized delegate (see below for more information about delegates).

Pass the burn intents to the /v1/transfer endpoint of the API to request an attestation from the Gateway System. If the transfer is valid, the API responds with an encoded attestation and signature that is valid for the destination domain.

Next, make a contract call to the minter contract on the destination chain using the attestation and signature. In order to atomically compose this mint with other onchain actions, use a multi-call contract. Note that if destinationCaller is specified in any of the transfer specs, it must match the sender of the transaction (this can be used to prevent front-running a mint when it is intended to be composed with other actions in the same transaction).

The Gateway System ensures that if an attestation is used, the corresponding burn transaction is submitted to all involved source chains.

There are two ways to remove USDC from the Gateway system: instant transfers and trustless withdrawals.

The destination chain of a transfer may be the same as the source chain. This means that to withdraw USDC from the wallet contract on the same chain, the transfer flow described in the preceding section applies. The only fee for same-chain withdrawals is to cover gas for the burn transaction (no other transfer fee is charged).

The reason same-chain withdrawals still involve a mint and burn rather than just a transfer out of the wallet contract is to ensure that there are no methods of removing USDC from the wallet contract that don't involve a user signature.

In the unlikely event that Circle's APIs are down for an extended period or service is unavailable for any other reason, users can trustlessly withdraw USDC with a delay.

First, make a contract call to the initiateWithdrawal method with the desired amount to withdrawal. After a delay of 7 days, make a contract call to the withdraw method to complete the withdrawal.

Because the Gateway System needs to statically verify the signature on all burn intents without involving any onchain state and guarantee that the signature is valid at the time of the burn transaction, SCA signatures such as EIP-1271 signatures cannot be accepted. Burn intents must be signed by an EOA.

There is a delegate mechanism built into Gateway that allows SCAs to make use of the protocol. Any user can add one or more other addresses that are allowed to sign transfer requests on their behalf. This acts as a full allowance for the deposited USDC.

These delegate addresses should be EOAs capable of producing a valid ECDSA signature to be effective. For EOAs that have upgraded to SCAs using EIP-7702, this delegation is unnecessary, since there is still an underlying EOA that can produce the necessary signature directly.

To add a delegate, use the addDelegate method on the wallet contract. This needs to be done for each wallet contract where the depositor address holds USDC across all chains.

To remove a delegate (for key rotation or other purposes), use the removeDelegate method of the wallet contract. This needs to be done for each wallet contract where the depositor address holds USDC across all chains.

Note that when delegates are removed, signatures they produced are still valid for the purpose of fulfilling burn intents onchain. This ensures that burns may be executed safely even in the event of a revocation. The API still reflects revocations as soon as they are finalized onchain.

Did this page help you?
© 2023-2025 Circle Technology Services, LLC. All rights reserved.