Skip to main content
Programmable addresses enable routing and settlement rules to be attached to a persistent address, which can be scoped to a product-specific domain or affiliated with a user’s wallet. When funds arrive, they swap and settle automatically. No manual bridging. No extra transactions. Each programmable address is a smart contract deterministically derived from a wallet address using CREATE2—the same input always produces the same address on every supported chain. Compute it once, and it exists forever: a permanent endpoint that can be shared publicly, embedded in invoices, or surfaced in a product UI.

How it works

When tokens arrive at a programmable address, the attached logic executes automatically:
  1. Tokens land at the programmable address
  2. The contract deploys on first deposit only—no gas until funds actually arrive
  3. The pre-programmed action executes
The sender makes a normal transfer. They don’t bridge, they don’t use a special app. The programmable address handles swapping, bridging, or settling—whatever it’s programmed to do.

Step-by-step flow

  1. Address generation: Request a programmable address for your destination wallet
  2. Deterministic computation: The factory computes a unique EVM address from the destination using CREATE2
  3. Token transfer: Send USDC to the programmable address on Base
  4. Contract deployment: The system detects the deposit and deploys the contract if needed
  5. Action execution: The pre-programmed logic executes—for cross-chain deposits, this creates an intent via createIntent()
  6. Fulfillment: Solvers compete to fulfill the intent, delivering tokens to the destination wallet

Supported chains and tokens

Programmable addresses currently support:
Details
Source chainBase (chain ID 8453)
Deposit tokenUSDC
DestinationSolana
Additional chains and tokens will be added over time.

Cross-chain deposit: the first programmable action

The most common use of programmable addresses is cross-chain deposit: USDC arrives on Base and settles to a Solana wallet automatically. Users share one address, funds arrive on their home chain regardless of where the sender is. The architecture supports arbitrarily encoded actions and more complex settlement rules. Deposit is the first programmable action, not the last.

Architecture

Components

Address Factory

The factory contract manages programmable address generation:
  • Computes deterministic addresses via getDepositAddress()
  • Deploys programmable address contracts via deploy()
  • Stores immutable configuration for destination chain, tokens, and Portal

Programmable Address Contract

Individual programmable address contracts handle token reception and action execution:
  • Receives tokens from users
  • Executes the programmed action (e.g., creates intents via createIntent())
  • Supports refunds via refund() for expired intents

Built on Routes

Programmable addresses use Routes as the execution layer. When the programmed action involves cross-chain movement, the programmable address creates a Routes intent. Solvers compete to fulfill it. Provers verify execution. This means programmable addresses inherit Routes’ properties:
  • Fast execution through solver competition
  • Cryptographic proof of delivery
  • Automatic refunds if an intent expires unfulfilled

What you can build

Cross-chain receiving

Give any wallet the ability to receive from any chain. Users share one address, funds arrive on their home chain regardless of where the sender is.

Programmable payment flows

Accept payments from any chain and route them automatically—to a treasury, into a yield protocol, split between multiple destinations. The logic executes on every deposit without manual intervention.

Automated bridging for exchanges

Users withdraw to a Solana address. The exchange sends to the programmable address on any EVM chain. Funds bridge and arrive on Solana. No bridge integration, no user-facing complexity, no support tickets about stuck transactions.

One-step cross-chain deposits

Users deposit into your protocol from any chain. The programmable address bridges and deposits in a single flow. Users don’t think about which chain your contracts are on—they just deposit.

Configuration

Each factory is configured with immutable parameters:
ParameterTypeDescription
destinationChainuint64Target chain ID (Solana)
sourceTokenaddressToken address on source chain
targetTokenbytes32Token address on destination
portalAddressaddressRoutes Portal contract address
proverAddressaddressCross-chain prover address
destinationPortalbytes32Portal on destination chain
intentDeadlineDurationuint64Time window for intent fulfillment

Data types

Programmable Address

interface ProgrammableAddress {
  chainId: number;
  factoryAddress: Address;
  solanaAddress: Hex;
  depositor: Address;
  evmDepositAddress: Address;
  isDeployed: boolean;
  deploymentTxHash?: Hex;
  deploymentBlockNumber?: bigint;
  lastCheckedBalance: bigint;
  lastBalanceCheckAt: Date;
  createdAt: Date;
  updatedAt: Date;
}

Intent

interface Intent {
  chainId: number;
  intentHash: Hex;
  depositAddress: Address;
  factoryAddress: Address;
  solanaAddress: Hex;
  amount: bigint;
  status: 'pending' | 'funded' | 'fulfilled' | 'expired' | 'failed';
  txHash: Hex | null;
  blockNumber: bigint | null;
  createdAt: Date;
  updatedAt: Date;
  fulfilledAt: Date | null;
  fulfilledTxHash: Hex | null;
  error: string | null;
  lastCheckedAt: Date;
}