<!--
Sitemap:
- [Tempo](/index): Explore Tempo's blockchain documentation, integration guides, and protocol specs. Build low-cost, high-throughput payment applications.
- [Accounts SDK – Getting Started](/accounts/): Set up the Tempo Accounts SDK to create, manage, and interact with accounts on Tempo.
- [Changelog](/changelog)
- [Tempo CLI](/cli/): A single binary for using Tempo Wallet from the terminal, making paid HTTP requests, and running a Tempo node.
- [Tempo Ecosystem Infrastructure](/ecosystem/): Explore Tempo's ecosystem partners providing bridges, wallets, node infrastructure, data analytics, security, and more for building on Tempo.
- [Learn](/learn/): Explore stablecoin use cases and Tempo's payments-optimized blockchain architecture for remittances, payouts, and embedded finance.
- [Tempo Protocol](/protocol/): Technical specifications and reference documentation for the Tempo blockchain protocol, purpose-built for global payments at scale.
- [SDKs](/sdk/): Integrate Tempo into your applications with SDKs for TypeScript, Go, Rust, and Foundry. Build blockchain apps in your preferred language.
- [Tempo CLI](/wallet/): A terminal client for Tempo wallet management, service discovery, and paid HTTP requests via the Machine Payments Protocol.
- [FAQ](/accounts/faq): Frequently asked questions about the Tempo Accounts SDK.
- [Deploying to Production](/accounts/production): Things to consider before deploying your application with the Tempo Accounts SDK to production.
- [Handlers](/accounts/server/): Server-side handlers for the Tempo Accounts SDK.
- [tempo download](/cli/download): Download chain snapshots for faster initial sync of a Tempo node.
- [tempo node](/cli/node): Command reference for running a Tempo node.
- [tempo request](/cli/request): A curl-like HTTP client that handles MPP payment negotiation automatically.
- [tempo wallet](/cli/wallet): Use Tempo Wallet from the terminal — authenticate, check balances, manage access keys, and discover services.
- [Block Explorers](/ecosystem/block-explorers): View transactions, blocks, accounts, and token activity on the Tempo network with block explorers.
- [Bridges & Exchanges](/ecosystem/bridges): Move assets to and from Tempo with cross-chain bridges and access deep DEX liquidity with exchange infrastructure.
- [Data & Analytics](/ecosystem/data-analytics): Query blockchain data on Tempo with indexers, analytics platforms, oracles, and monitoring tools.
- [Node Infrastructure](/ecosystem/node-infrastructure): Connect to Tempo with reliable RPC endpoints and managed node services from infrastructure partners.
- [Issuance & Orchestration](/ecosystem/orchestration): Move money globally between local currencies and stablecoins. Issue, transfer, and manage stablecoins on Tempo.
- [Security & Compliance](/ecosystem/security-compliance): Transaction scanning, threat detection, and compliance infrastructure for Tempo applications.
- [Smart Contract Libraries](/ecosystem/smart-contract-libraries): Build with account abstraction and programmable smart contract wallets on Tempo.
- [Wallets](/ecosystem/wallets): Integrate embedded, custodial, and institutional wallet infrastructure into your Tempo application.
- [!Replace Me!](/guide/_template)
- [Bridge via LayerZero](/guide/bridge-layerzero): Bridge tokens to and from Tempo using LayerZero. Covers Stargate pools and standard OFT adapters with cast commands and TypeScript examples.
- [Bridge via Relay](/guide/bridge-relay): Bridge tokens to and from Tempo using Relay. Includes supported token discovery, curl commands, TypeScript examples with viem, and status tracking.
- [Getting Funds on Tempo](/guide/getting-funds): Bridge assets to Tempo, add funds in Tempo Wallet, or use the faucet on testnet.
- [Stablecoin Issuance](/guide/issuance/): Create and manage your own stablecoin on Tempo. Issue tokens, manage supply, and integrate with Tempo's payment infrastructure.
- [Agentic Payments](/guide/machine-payments/): Make agentic payments using the Machine Payments Protocol (MPP) on Tempo — charge for APIs, MCP tools, and digital content with TIP-20 stablecoins.
- [Tempo Node](/guide/node/): Run your own Tempo node for direct network access. Set up RPC nodes for API access or validator nodes to participate in consensus.
- [Stablecoin Payments](/guide/payments/): Send and receive stablecoin payments on Tempo. Integrate payments with flexible fee options, sponsorship capabilities, and parallel transactions.
- [Connect to Tempo Zones](/guide/private-zones/): Learn how Tempo Zones work alongside the public chain and follow guides for depositing, sending within a zone, routing pathUSD across zones, swapping into betaUSD, and withdrawing.
- [Exchange Stablecoins](/guide/stablecoin-dex/): Trade between stablecoins on Tempo's enshrined DEX. Execute swaps, provide liquidity, and query the onchain orderbook for optimal pricing.
- [Use Tempo Transactions](/guide/tempo-transaction/): Learn how to use Tempo Transactions for configurable fee tokens, fee sponsorship, batch calls, access keys, and concurrent execution.
- [Create & Use Accounts](/guide/use-accounts/): Create and integrate Tempo accounts with the universal Tempo Wallet or domain-bound passkeys.
- [Using Tempo with AI](/guide/using-tempo-with-ai): Give your AI coding agent Tempo documentation context and a wallet for autonomous transactions.
- [Partners](/learn/partners): Discover Tempo's ecosystem of stablecoin issuers, wallets, custody providers, compliance tools, and ramps.
- [What are stablecoins?](/learn/stablecoins): Learn what stablecoins are, how they maintain value through reserves, and the payment use cases they enable for businesses globally.
- [Tempo](/learn/tempo/): Discover Tempo, the payments-first blockchain with instant settlement, predictably low fees, and native stablecoin support.
- [Exchanging Stablecoins](/protocol/exchange/): Tempo's enshrined decentralized exchange for trading between stablecoins with optimal pricing, limit orders, and flip orders for liquidity provision.
- [Transaction Fees](/protocol/fees/): Pay transaction fees in any USD stablecoin on Tempo. No native token required—fees are paid directly in TIP-20 stablecoins with automatic conversion.
- [Tempo RPC Reference](/protocol/rpc/): Reference for Tempo-specific JSON-RPC methods in the tempo, consensus, and admin namespaces, plus modified eth_ behavior.
- [Tempo Improvement Proposals (TIPs)](/protocol/tips/)
- [Tempo Transactions](/protocol/transactions/): Learn about Tempo Transactions, a new EIP-2718 transaction type with passkey support, fee sponsorship, batching, and concurrent execution.
- [Tempo Zones](/protocol/zones/): Tempo Zones are private execution environments on Tempo Mainnet where balances, transfers, and transaction history are invisible to the public chain.
- [Connect to the Network](/quickstart/connection-details): Connect to Tempo using browser wallets, CLI tools, or direct RPC endpoints. Get chain ID, URLs, and configuration details.
- [Developer Tools](/quickstart/developer-tools): Explore Tempo's developer ecosystem with indexers, embedded wallets, node infrastructure, and analytics partners for building payment apps.
- [EVM Differences](/quickstart/evm-compatibility): Learn how Tempo differs from Ethereum. Understand wallet behavior, fee token selection, VM layer changes, and fast finality consensus.
- [Faucet](/quickstart/faucet): Get free test stablecoins on Tempo Testnet. Connect your wallet or enter any address to receive pathUSD, AlphaUSD, BetaUSD, and ThetaUSD.
- [Integrate Tempo](/quickstart/integrate-tempo): Build on Tempo Testnet. Connect to the network, explore SDKs, and follow guides for accounts, payments, and stablecoin issuance.
- [Predeployed Contracts](/quickstart/predeployed-contracts): Discover Tempo's predeployed system contracts including TIP-20 Factory, Fee Manager, Stablecoin DEX, and standard utilities like Multicall3.
- [Tempo Token List Registry](/quickstart/tokenlist)
- [Contract Verification](/quickstart/verify-contracts): Verify your smart contracts on Tempo using contracts.tempo.xyz. Sourcify-compatible verification with Foundry integration.
- [Wallet Integration Guide](/quickstart/wallet-developers): Integrate Tempo into your wallet. Handle fee tokens, configure gas display, and deliver enhanced stablecoin payment experiences for users.
- [Foundry for Tempo](/sdk/foundry/): Build, test, and deploy smart contracts on Tempo using Foundry. Access Tempo protocol features with forge, cast, anvil, and chisel.
- [Go](/sdk/go/): Build blockchain apps with the Tempo Go SDK. Send transactions, batch calls, and handle fee sponsorship with idiomatic Go code.
- [Python](/sdk/python/): Build blockchain apps with the Tempo Python SDK. Send transactions, batch calls, and handle fee sponsorship using web3.py.
- [Rust](/sdk/rust/): Build blockchain apps with the Tempo Rust SDK using Alloy. Query chains, send transactions, and manage tokens with type-safe Rust code.
- [TypeScript SDKs](/sdk/typescript/): Build blockchain apps with Tempo using Viem and Wagmi. Send transactions, manage tokens, and integrate AMM pools with TypeScript.
- [Tempo Wallet CLI Recipes](/wallet/recipes): Use practical Tempo Wallet CLI recipes for service discovery, paid requests, session management, and funding or transfers.
- [Tempo CLI Reference](/wallet/reference): Complete command and flag reference for tempo wallet and tempo request.
- [Use Tempo Wallet CLI with Agents](/wallet/use-with-agents): Connect Tempo Wallet CLI to your agent and understand the built-in features that make agent-driven paid requests reliable and safe.
- [Adapters](/accounts/api/adapters): Pluggable adapters for the Tempo Accounts SDK Provider.
- [dialog](/accounts/api/dialog): Adapter for the Tempo Wallet dialog, an embedded iframe or popup for account management.
- [Dialog.iframe](/accounts/api/dialog.iframe): Embed the Tempo Wallet auth UI in an iframe dialog element.
- [Dialog.popup](/accounts/api/dialog.popup): Open the Tempo Wallet auth UI in a popup window.
- [Dialog](/accounts/api/dialogs): Dialog modes for embedding the Tempo Wallet.
- [Expiry](/accounts/api/expiry): Utility functions for computing access key expiry timestamps.
- [local](/accounts/api/local): Key-agnostic adapter for defining arbitrary account types and signing mechanisms.
- [Provider](/accounts/api/provider): Create an EIP-1193 provider for managing accounts on Tempo.
- [webAuthn](/accounts/api/webAuthn): Adapter for passkey-based accounts using WebAuthn registration and authentication.
- [WebAuthnCeremony](/accounts/api/webauthnceremony): Pluggable strategy for WebAuthn registration and authentication ceremonies.
- [WebAuthnCeremony.from](/accounts/api/webauthnceremony.from): Create a WebAuthnCeremony from a custom implementation.
- [WebAuthnCeremony.server](/accounts/api/webauthnceremony.server): Server-backed WebAuthn ceremony that delegates to a remote handler.
- [Create & Use Accounts](/accounts/guides/create-and-use-accounts): Choose between universal wallet experiences or domain-bound passkey accounts for your app.
- [eth_fillTransaction](/accounts/rpc/eth_fillTransaction): Fills missing transaction fields and returns wallet-aware metadata.
- [eth_sendTransaction](/accounts/rpc/eth_sendTransaction): Send a transaction from the connected account.
- [eth_sendTransactionSync](/accounts/rpc/eth_sendTransactionSync): Send a transaction and wait for the receipt.
- [personal_sign](/accounts/rpc/personal_sign): Sign a message with the connected account.
- [wallet_authorizeAccessKey](/accounts/rpc/wallet_authorizeAccessKey): Authorize an access key for delegated transaction signing.
- [wallet_connect](/accounts/rpc/wallet_connect): Connect account(s) with optional capabilities like access key authorization.
- [wallet_disconnect](/accounts/rpc/wallet_disconnect): Disconnect the connected account(s).
- [wallet_getBalances](/accounts/rpc/wallet_getBalances): Get token balances for an account.
- [wallet_getCallsStatus](/accounts/rpc/wallet_getCallsStatus): Get the status of a batch of calls sent via wallet_sendCalls.
- [wallet_getCapabilities](/accounts/rpc/wallet_getCapabilities): Get account capabilities for specified chains.
- [wallet_revokeAccessKey](/accounts/rpc/wallet_revokeAccessKey): Revoke a previously authorized access key.
- [wallet_sendCalls](/accounts/rpc/wallet_sendCalls): Send a batch of calls from the connected account.
- [Handler.compose](/accounts/server/handler.compose): Compose multiple server handlers into a single handler.
- [Handler.feePayer (Deprecated)](/accounts/server/handler.feePayer): Deprecated — use Handler.relay with feePayer option instead.
- [Handler.relay](/accounts/server/handler.relay): Server handler that proxies certain RPC requests with wallet-aware enrichment.
- [Handler.webAuthn](/accounts/server/handler.webAuthn): Server-side WebAuthn ceremony handler for registration and authentication.
- [Kv](/accounts/server/kv): Key-value store adapters for server-side persistence.
- [tempoWallet](/accounts/wagmi/tempoWallet): Wagmi connector for the Tempo Wallet dialog.
- [webAuthn](/accounts/wagmi/webAuthn): Wagmi connector for passkey-based WebAuthn accounts.
- [Create a Stablecoin](/guide/issuance/create-a-stablecoin): Create your own stablecoin on Tempo using the TIP-20 token standard. Deploy tokens with built-in compliance features and role-based permissions.
- [Distribute Rewards](/guide/issuance/distribute-rewards): Distribute rewards to token holders using TIP-20's built-in reward mechanism. Allocate tokens proportionally based on holder balances.
- [Manage Your Stablecoin](/guide/issuance/manage-stablecoin): Configure stablecoin permissions, supply limits, and compliance policies. Grant roles, set transfer policies, and control pause/unpause functionality.
- [Mint Stablecoins](/guide/issuance/mint-stablecoins): Mint new tokens to increase your stablecoin's total supply. Grant the issuer role and create tokens with optional memos for tracking.
- [Use Your Stablecoin for Fees](/guide/issuance/use-for-fees): Enable users to pay transaction fees using your stablecoin. Add fee pool liquidity and integrate with Tempo's flexible fee payment system.
- [Agent Quickstart](/guide/machine-payments/agent): Use the tempo CLI to discover services, preview costs, and make paid requests from a terminal or AI agent — no SDK required.
- [Client Quickstart](/guide/machine-payments/client): Set up an MPP client on Tempo. Polyfill fetch to automatically pay for 402 responses with TIP-20 stablecoins.
- [Accept One-Time Payments](/guide/machine-payments/one-time-payments): Charge per request on Tempo using the mppx charge intent. Each request triggers a TIP-20 transfer that settles in ~500ms.
- [Accept Pay-As-You-Go Payments](/guide/machine-payments/pay-as-you-go): Session-based billing on Tempo with MPP payment channels. Clients deposit funds, sign off-chain vouchers, and pay per request without on-chain latency.
- [Server Quickstart](/guide/machine-payments/server): Add payment gating to any HTTP endpoint on Tempo with mppx middleware for Next.js, Hono, Express, and the Fetch API.
- [Accept Streamed Payments](/guide/machine-payments/streamed-payments): Per-token billing over Server-Sent Events on Tempo. Stream content word-by-word and charge per unit using MPP sessions with SSE.
- [Installation](/guide/node/installation): Install Tempo node using pre-built binaries, build from source with Rust, or run with Docker. Get started in minutes with tempoup.
- [Network Upgrades and Releases](/guide/node/network-upgrades): Timeline and details for Tempo network upgrades and important releases for node operators.
- [Operate your validator node](/guide/node/operate-validator): Day-to-day operations for Tempo validators. Node lifecycle, monitoring, metrics, log management, and Grafana dashboards.
- [Running an RPC Node](/guide/node/rpc): Set up and run a Tempo RPC node for API access. Download snapshots, configure systemd services, and monitor node health and sync status.
- [System Requirements](/guide/node/system-requirements): Minimum and recommended hardware specs for running Tempo RPC and validator nodes. CPU, RAM, storage, network, and port requirements.
- [Running a validator node](/guide/node/validator): Configure and run a Tempo validator node. Generate signing keys, participate in DKG ceremonies, and troubleshoot consensus issues.
- [ValidatorConfig V2](/guide/node/validator-config-v2): Manage your validator with ValidatorConfig V2. Self-service key rotation, IP updates, and ownership transfer.
- [Accept a Payment](/guide/payments/accept-a-payment): Accept stablecoin payments in your application. Verify transactions, listen for transfer events, and reconcile payments using memos.
- [Pay Fees in Any Stablecoin](/guide/payments/pay-fees-in-any-stablecoin): Configure users to pay transaction fees in any supported stablecoin. Eliminate the need for a separate gas token with Tempo's flexible fee system.
- [Send a Payment](/guide/payments/send-a-payment): Send stablecoin payments between accounts on Tempo. Include optional memos for reconciliation and tracking with TypeScript, Rust, or Solidity.
- [Send Parallel Transactions](/guide/payments/send-parallel-transactions): Submit multiple transactions concurrently using Tempo's expiring nonce system under-the-hood.
- [Sponsor User Fees](/guide/payments/sponsor-user-fees): Enable gasless transactions by sponsoring fees for your users. Set up a fee payer service and improve UX by removing friction from payment flows.
- [Attach a Transfer Memo](/guide/payments/transfer-memos)
- [Connect to a Zone](/guide/private-zones/connect-to-a-zone): Connect to Tempo Zones on testnet using Zone A and Zone B RPC URLs, chain IDs, and a minimal viem client setup for private flows.
- [Deposit to a Zone](/guide/private-zones/deposit-to-a-zone): Deposit pathUSD from your public-chain balance into Zone A and confirm the resulting zone balance.
- [Send tokens across zones](/guide/private-zones/send-tokens-across-zones): Send pathUSD from Zone A into Zone B by routing a same-token withdrawal through Tempo's L1 router and confirming the target deposit.
- [Send tokens within a zone](/guide/private-zones/send-tokens-within-a-zone): Send pathUSD inside Zone A with a signed zone transfer and confirm the updated zone balance.
- [Swap stablecoins across zones](/guide/private-zones/swap-across-zones): Swap pathUSD from Zone A into betaUSD on Zone B by routing a zone withdrawal through Tempo's L1 router and confirming the target deposit.
- [Withdraw from a Zone](/guide/private-zones/withdraw-from-a-zone): Withdraw pathUSD from Zone A back to your public-chain balance with a direct zone outbox withdrawal.
- [Executing Swaps](/guide/stablecoin-dex/executing-swaps): Learn to execute instant stablecoin swaps on Tempo's DEX. Get price quotes, set slippage protection, and batch approvals with swaps.
- [Managing Fee Liquidity](/guide/stablecoin-dex/managing-fee-liquidity): Add and remove liquidity in the Fee AMM to enable stablecoin fee conversions. Monitor pools, check LP balances, and rebalance reserves.
- [Providing Liquidity](/guide/stablecoin-dex/providing-liquidity): Place limit and flip orders to provide liquidity on the Stablecoin DEX orderbook. Learn to manage orders and set prices using ticks.
- [View the Orderbook](/guide/stablecoin-dex/view-the-orderbook): Inspect Tempo's onchain orderbook using SQL queries. View spreads, order depth, individual orders, and recent trade prices with indexed data.
- [Add Funds to Your Balance](/guide/use-accounts/add-funds): Get test stablecoins on Tempo Testnet using the faucet. Request pathUSD, AlphaUSD, BetaUSD, and ThetaUSD tokens for development and testing.
- [Batch Transactions](/guide/use-accounts/batch-transactions)
- [Connect to Wallets](/guide/use-accounts/connect-to-wallets): Connect your application to EVM-compatible wallets like MetaMask on Tempo. Set up Wagmi connectors and add the Tempo network to user wallets.
- [Embed Passkey Accounts](/guide/use-accounts/embed-passkeys): Create domain-bound passkey accounts on Tempo using WebAuthn for secure, passwordless authentication with biometrics like Face ID and Touch ID.
- [Embed Tempo Wallet](/guide/use-accounts/embed-tempo-wallet): Embed the Tempo Wallet dialog into your application for a universal wallet experience with account management, passkeys, and fee sponsorship.
- [Scheduled Transactions](/guide/use-accounts/scheduled-transactions)
- [WebAuthn & P256 Signatures](/guide/use-accounts/webauthn-p256-signatures)
- [Onchain FX](/learn/tempo/fx): Access foreign exchange liquidity directly onchain with regulated non-USD stablecoin issuers and multi-currency fee payments on Tempo.
- [Agentic Payments](/learn/tempo/machine-payments): The Machine Payments Protocol (MPP) is an open standard for machine-to-machine payments, co-authored by Stripe and Tempo.
- [Tempo Transactions](/learn/tempo/modern-transactions): Native support for gas sponsorship, batch transactions, scheduled payments, and passkey authentication built into Tempo's protocol.
- [TIP-20 Tokens](/learn/tempo/native-stablecoins): Tempo's stablecoin token standard with payment lanes, stable fees, reconciliation memos, and built-in compliance for regulated issuers.
- [Performance](/learn/tempo/performance): High throughput and sub-second finality built on Reth SDK and Simplex Consensus for payment applications requiring instant settlement.
- [Privacy](/learn/tempo/privacy): Explore Tempo's opt-in privacy features enabling private balances and confidential transfers while maintaining issuer compliance.
- [Power AI agents with programmable money](/learn/use-cases/agentic-commerce): Power autonomous AI agents with programmable stablecoin payments for goods, services, and digital resources in real time.
- [Bring embedded finance to life with stablecoins](/learn/use-cases/embedded-finance): Enable platforms and marketplaces to streamline partner payouts, lower payment costs, and launch rewarding loyalty programs.
- [Send global payouts instantly](/learn/use-cases/global-payouts): Deliver instant, low-cost payouts to contractors, merchants, and partners worldwide with stablecoins, bypassing slow banking rails.
- [Enable true pay-per-use pricing](/learn/use-cases/microtransactions): Enable true pay-per-use pricing with sub-cent payments for APIs, content, IoT services, and machine-to-machine commerce.
- [Stablecoins for Payroll](/learn/use-cases/payroll): Faster payroll funding, cheaper cross-border payouts, and new revenue streams for payroll providers using stablecoins.
- [Send money home faster and cheaper](/learn/use-cases/remittances): Send cross-border payments faster and cheaper with stablecoins, eliminating correspondent banks and reducing transfer costs.
- [Move treasury liquidity instantly across borders](/learn/use-cases/tokenized-deposits): Move treasury liquidity instantly across borders with real-time visibility into global cash positions using tokenized deposits.
- [Consensus and Finality](/protocol/blockspace/consensus): Tempo uses Simplex BFT via Commonware for deterministic sub-second finality with Byzantine fault tolerance.
- [Blockspace Overview](/protocol/blockspace/overview): Technical specification for Tempo block structure including header fields, payment lanes, and system transaction ordering.
- [Payment Lane Specification](/protocol/blockspace/payment-lane-specification): Technical specification for Tempo payment lanes ensuring dedicated blockspace for payment transactions with predictable fees during congestion.
- [DEX Balance](/protocol/exchange/exchange-balance): Hold token balances directly on the Stablecoin DEX to save gas costs on trades, receive maker proceeds automatically, and trade more efficiently.
- [Executing Swaps](/protocol/exchange/executing-swaps): Learn how to execute swaps and quote prices on Tempo's Stablecoin DEX with exact-in and exact-out swap functions and slippage protection.
- [Providing Liquidity](/protocol/exchange/providing-liquidity): Provide liquidity on Tempo's DEX using limit orders and flip orders. Earn spreads while facilitating stablecoin trades with price-time priority.
- [Quote Tokens](/protocol/exchange/quote-tokens): Quote tokens determine trading pairs on Tempo's DEX. Each TIP-20 specifies a quote token, with pathUSD available as an optional neutral choice.
- [Stablecoin DEX](/protocol/exchange/spec): Technical specification for Tempo's enshrined DEX with price-time priority orderbook, flip orders, and multi-hop routing for stablecoin trading.
- [Fee AMM Overview](/protocol/fees/fee-amm/): Understand how the Fee AMM automatically converts transaction fees between stablecoins, enabling users to pay in any supported token.
- [Fee Specification](/protocol/fees/spec-fee): Technical specification for Tempo's fee system covering multi-token fee payment, fee sponsorship, token preferences, and validator payouts.
- [Fee AMM Specification](/protocol/fees/spec-fee-amm): Technical specification for the Fee AMM enabling automatic stablecoin conversion for transaction fees with fixed-rate swaps and MEV protection.
- [TIP-20 Rewards](/protocol/tip20-rewards/overview): Built-in reward distribution mechanism for TIP-20 tokens enabling efficient, opt-in proportional rewards to token holders at scale.
- [TIP-20 Rewards Distribution](/protocol/tip20-rewards/spec): Technical specification for the TIP-20 reward distribution system using reward-per-token accumulator pattern for scalable pro-rata rewards.
- [TIP-20 Token Standard](/protocol/tip20/overview): TIP-20 is Tempo's native token standard for stablecoins with built-in fee payment, payment lanes, transfer memos, and compliance policies.
- [TIP20](/protocol/tip20/spec): Technical specification for TIP-20, the optimized token standard extending ERC-20 with memos, rewards distribution, and policy integration.
- [TIP-403 Policy Registry](/protocol/tip403/overview): Learn how TIP-403 enables TIP-20 tokens to enforce access control through a shared policy registry with whitelist and blacklist support.
- [Overview](/protocol/tip403/spec): Technical specification for TIP-403, the policy registry system enabling whitelist and blacklist access control for TIP-20 tokens on Tempo.
- [TIP Title](/protocol/tips/_tip_template): Short description for SEO
- [TIP Process](/protocol/tips/tip-0000): Defines the Tempo Improvement Proposal lifecycle from draft to production.
- [State Creation Cost Increase](/protocol/tips/tip-1000): Increased gas costs for state creation operations to protect Tempo from adversarial state growth attacks.
- [Place-only mode for next quote token](/protocol/tips/tip-1001): A new DEX function for creating trading pairs against a token's staged next quote token, to allow orders to be placed on it.
- [Prevent crossed orders and allow same-tick flip orders](/protocol/tips/tip-1002): Changes to the Stablecoin DEX that prevent placing orders that would cross existing orders on the opposite side of the book, and allow flip orders to flip to the same tick.
- [Client order IDs](/protocol/tips/tip-1003): Addition of client order IDs to the Stablecoin DEX, allowing users to specify their own order identifiers for idempotency and easier order tracking.
- [Permit for TIP-20](/protocol/tips/tip-1004): Addition of EIP-2612 permit functionality to TIP-20 tokens, enabling gasless approvals via off-chain signatures.
- [Fix ask swap rounding loss](/protocol/tips/tip-1005): A fix for a rounding bug in the Stablecoin DEX where partial fills on ask orders can cause small amounts of quote tokens to be lost.
- [Burn At for TIP-20 Tokens](/protocol/tips/tip-1006): The burnAt function for TIP-20 tokens, enabling authorized administrators to burn tokens from any address.
- [Fee Token Introspection](/protocol/tips/tip-1007): Addition of fee token introspection functionality to the FeeManager precompile, enabling smart contracts to query the fee token being used for the current transaction.
- [Expiring Nonces](/protocol/tips/tip-1009): Time-bounded replay protection using transaction hashes instead of sequential nonce management.
- [Mainnet Gas Parameters](/protocol/tips/tip-1010): Initial gas parameters for Tempo mainnet launch including base fee pricing, payment lane capacity, and transaction gas limits.
- [Enhanced Access Key Permissions](/protocol/tips/tip-1011): Extends Access Keys with periodic spending limits, destination/function scoping, and limited calldata recipient scoping.
- [Compound Transfer Policies](/protocol/tips/tip-1015): Extends TIP-403 with compound policies that specify different authorization rules for senders and recipients.
- [Exempt Storage Creation from Gas Limits](/protocol/tips/tip-1016): Storage creation gas costs are charged but don't count against transaction or block gas limits, using a reservoir model aligned with EIP-8037 for correct GAS opcode semantics and EVM compatibility.
- [Validator Config V2 precompile](/protocol/tips/tip-1017): Validator Config V2 precompile for improved management of consensus participants
- [Signature Verification Precompile](/protocol/tips/tip-1020): A precompile for verifying Tempo signatures onchain.
- [Virtual Addresses for TIP-20 Deposit Forwarding](/protocol/tips/tip-1022): Precompile-native virtual addresses that auto-forward TIP-20 deposits to a registered master wallet, eliminating sweep transactions.
- [Allow same-tick flip orders](/protocol/tips/tip-1030): Relaxes the placeFlip validation to allow flipTick to equal tick, enabling flip orders that flip to the same price.
- [Embed consensus context in the block Header](/protocol/tips/tip-1031): Embed consensus context into the block header
- [T2 Hardfork Bug Fixes](/protocol/tips/tip-1036): Meta TIP collecting all audit-driven bug fixes and hardening changes gated behind the T2 hardfork.
- [T3 Hardfork Meta TIP](/protocol/tips/tip-1038): Meta TIP collecting all bug fixes, security hardening, and gas correctness changes gated behind the T3 hardfork.
- [Account Keychain Precompile](/protocol/transactions/AccountKeychain): Technical specification for the Account Keychain precompile managing access keys with expiry timestamps and per-token spending limits.
- [EIP-4337 Comparison](/protocol/transactions/eip-4337): How Tempo Transactions achieve EIP-4337 goals without bundlers, paymasters, or EntryPoint contracts.
- [EIP-7702 Comparison](/protocol/transactions/eip-7702): How Tempo Transactions extend EIP-7702 delegation with additional signature schemes and native features.
- [Tempo Transaction](/protocol/transactions/spec-tempo-transaction): Technical specification for the Tempo transaction type (EIP-2718) with WebAuthn signatures, parallelizable nonces, gas sponsorship, and batching.
- [T2 Network Upgrade](/protocol/upgrades/t2): Details and timeline for the T2 network upgrade including compound transfer policies, Validator Config V2, permit support for TIP-20, and audit-driven bug fixes.
- [T3 Network Upgrade](/protocol/upgrades/t3): Details and timeline for the T3 network upgrade, including enhanced access keys, signature verification, virtual addresses, and security hardening and gas correctness fixes.
- [Accounts](/protocol/zones/accounts): Account-scoped access control on Tempo Zones, including private balances, private allowances, and the two-layer privacy model.
- [Tempo Zone Architecture](/protocol/zones/architecture): Architecture of Tempo Zones, including contract layout, sequencer management, chain IDs, and the trust model.
- [Zone Bridging](/protocol/zones/bridging): Deposit and withdraw TIP-20 tokens between Tempo Mainnet and Tempo Zones, including encrypted deposits and composable withdrawal callbacks.
- [Execution & Gas](/protocol/zones/execution): Specification for gas accounting, fee tokens, fixed TIP-20 gas costs, contract creation limits, and token management on Tempo Zones.
- [Zone Proving](/protocol/zones/proving): Batch submission and proof verification for Tempo zones, including the state transition function, ZK and TEE deployment modes, and ancestry proofs.
- [Zone RPC](/protocol/zones/rpc): Authenticated JSON-RPC interface for Tempo Zones with per-account scoping, timing side channel mitigations, and event filtering.
- [Foundry Integration](/sdk/foundry/mpp): Use Foundry tools (cast, forge, anvil, chisel) with MPP-gated RPC endpoints on Tempo — automatic 402 handling with zero config.
- [Signature Verification in Foundry](/sdk/foundry/signature-verifier): Verify secp256k1, P256, and WebAuthn signatures in smart contracts using the TIP-1020 SignatureVerifier precompile with Foundry.
- [Pay for Agent-to-Agent Services](/guide/machine-payments/use-cases/agent-to-agent): Hire agents for coding, design, writing, and email with Auto.exchange and AgentMail via MPP stablecoin payments on Tempo.
- [Pay for AI Models Per Request](/guide/machine-payments/use-cases/ai-model-access): Let your agents call OpenAI, Anthropic, Gemini, Mistral, and other LLMs without API keys using MPP stablecoin payments on Tempo.
- [Pay for Blockchain Data and Analytics](/guide/machine-payments/use-cases/blockchain-data): Query on-chain data from Alchemy, Allium, Nansen, Dune, and Codex using MPP stablecoin payments on Tempo — no API keys required.
- [Pay for Browser Automation and Web Scraping](/guide/machine-payments/use-cases/browser-automation): Run headless browsers, solve CAPTCHAs, and scrape web pages using Browserbase, 2Captcha, and Oxylabs via MPP on Tempo.
- [Pay for Compute and Code Execution](/guide/machine-payments/use-cases/compute-and-code-execution): Run code, deploy containers, and access GPU compute via MPP with stablecoin payments on Tempo — no cloud accounts needed.
- [Pay for Data Enrichment and Lead Generation](/guide/machine-payments/use-cases/data-enrichment-and-leads): Enrich contacts, find emails, profile companies, and generate leads using Apollo, Hunter, Clado, and more via MPP on Tempo.
- [Pay for Financial and Market Data](/guide/machine-payments/use-cases/financial-data): Access stock prices, forex rates, SEC filings, crypto data, and economic indicators via MPP with stablecoin payments on Tempo.
- [Pay for Image, Video, and Audio Generation](/guide/machine-payments/use-cases/image-and-media-generation): Generate images, videos, audio, and speech with fal.ai, OpenAI, Gemini, and Deepgram via MPP stablecoin payments on Tempo.
- [Pay for Maps, Geocoding, and Location Data](/guide/machine-payments/use-cases/location-and-maps): Access Google Maps, Mapbox, weather, and flight data via MPP with stablecoin payments on Tempo — no API keys required.
- [Monetize Your API with Agentic Payments](/guide/machine-payments/use-cases/monetize-your-api): Accept stablecoin payments for your API using MPP on Tempo. Charge per request without requiring signups, billing accounts, or API keys.
- [Pay for Object Storage and Git Repos](/guide/machine-payments/use-cases/storage): Store files and create Git repositories using MPP with stablecoin payments on Tempo — no cloud accounts required.
- [Pay for Translation and Language Services](/guide/machine-payments/use-cases/translation-and-language): Translate text, transcribe audio, and process language using DeepL, Deepgram, and other MPP services with stablecoin payments on Tempo.
- [Pay for Web Search and Research](/guide/machine-payments/use-cases/web-search-and-research): Let agents search the web, extract content, and crawl pages using MPP services like Parallel, Exa, Brave, and Firecrawl with stablecoin payments.
- [Setup](/sdk/typescript/prool/setup): Set up infinite pooled Tempo node instances in TypeScript with Prool for testing and local development of blockchain applications.
-->

# TIP-1022: Virtual Addresses for TIP-20 Deposit Forwarding

## Abstract

This TIP introduces **virtual addresses**: a reserved 20-byte address format that, when detected in TIP-20 recipient-bearing operations, causes the precompile to auto-credit a registered master wallet instead of the literal target address. This eliminates sweep transactions entirely for entities such as exchanges, ramps, and payment processors that generate per-user deposit addresses. Master registration is a one-time onchain call; deposit address derivation is fully offchain.

## Motivation

* **Eliminate sweep transactions.** Entities such as exchanges, ramps, and payment processors need to offer each customer a unique deposit address. Today, funds arriving at each address must be swept back to a central wallet in separate transactions, which is a large operational cost and burden at scale. Virtual addresses auto-credit the master wallet at the protocol level, making sweeps unnecessary.

* **Avoid the 250,000 gas new-account cost.** Tempo charges 250,000 gas to create state for a new address on first use. With virtual addresses, deposit addresses never create onchain state, so the first transfer to a new deposit address costs the same as any other transfer.

* **Prevent state bloat.** Without virtual addresses, each customer deposit address creates a new account in the state trie. At enterprise scale (millions of deposit addresses), this is significant and permanent state growth. Virtual addresses avoid this entirely: no accounts are created, regardless of how many deposit addresses a business generates.

***

# Specification

## Address Layout

Virtual addresses are standard 20-byte EVM addresses with the following reserved format:

```
[4-byte masterId] [10-byte MAGIC] [6-byte userTag]
= 20 bytes total
```

| Field | Bytes | Description |
|-------|-------|-------------|
| **masterId** | 4 | Deterministic identifier derived from `(masterAddress, salt)` via the registration hash. This is the registry lookup key. |
| **VIRTUAL\_MAGIC** | 10 | Fixed magic value `0xFDFDFDFDFDFDFDFDFDFD`. Identifies the address as virtual. |
| **userTag** | 6 | Opaque per-user identifier derived offchain by the operator. 48 bits support ~2.8×10^14 unique deposit addresses per master. |

### Why This Layout?

TIP-1022 intentionally places the 10-byte magic sequence in the **middle** of the address instead of at the beginning. This preserves more visually useful bytes at the front and back of the address for operators and users comparing deposit addresses in wallets, explorers, etc.

The 4-byte `masterId` is kept short to preserve room for a large `userTag`, while the 10-byte magic keeps the format highly unlikely to appear accidentally. The security implications of this tradeoff are discussed in **Security Considerations**.

## Conformance and Scope

TIP-1022 applies only to TIP-20 precompile recipient resolution for the entrypoints listed in **Transfer Path Modification**.

TIP-1022 does **not** alter TIP-20 methods that do not carry a recipient in the TIP-20 transfer path (e.g. `approve`, `burn`, `permit`) and does not alter non-TIP-20 protocol behavior.

Non-TIP-20 token transfers (e.g. ERC-20 contracts deployed on Tempo) to virtual addresses are **not** subject to TIP-1022 forwarding. Such transfers behave as standard EVM transfers to the literal address. Tokens sent this way may be irrecoverable — see **Risks and Limitations**.

`setRewardRecipient` is **not** a TIP-20 transfer-path operation and is therefore not subject to TIP-1022 recipient resolution. Implementations MUST reject virtual addresses when setting reward recipients so that rewards remain tied to canonical accounts rather than aliases.

## Reserved Virtual Address Format

Any address whose bytes `[4:14]` equal `VIRTUAL_MAGIC` is treated as a virtual address by the TIP-20 precompile.

If a TIP-20 transfer targets such an address:

* the precompile extracts the `masterId` from bytes `[0:4]`
* looks up the registered master
* credits the resolved master if registered
* otherwise reverts with `VirtualAddressUnregistered`

The literal virtual address never accumulates TIP-20 balance through standard TIP-20 transfer paths.

### Reserved Address Space

Addresses matching the virtual-address format occupy a reserved TIP-20 recipient namespace. A user who happens to control an EOA or contract whose address matches this format can still exist on Tempo and can still originate ordinary EVM transactions. However, TIP-20 transfers to such an address will follow TIP-1022 recipient resolution semantics rather than crediting the literal address.

Users who control such an address SHOULD NOT use it as a normal account on Tempo.

## Master ID Derivation

The `masterId` is deterministic and derived from the registration hash computed during `registerVirtualMaster()`:

```
registrationHash = keccak256(abi.encodePacked(msg.sender, salt))
masterId = bytes4(registrationHash[4:8])
```

The first 4 bytes of `registrationHash` are consumed by the proof-of-work check (see **Registration Proof of Work**); the `masterId` is extracted from bytes `[4:8]` of the same hash.

The salt is a `bytes32` value chosen by the caller. Callers MUST grind the salt to satisfy the 32-bit proof-of-work requirement. The resulting `masterId` is permanently bound to the registration address.

### Why `masterId` Registrations Are Immutable

TIP-1022 intentionally does not provide a mechanism to rotate or update the master address bound to a `masterId`. Allowing rotation would interact poorly with TIP-403 policies: a blacklisted master could rotate to a fresh address and resume receiving deposits, requiring policy enforcement to track `masterId`s in addition to addresses. Operators who need to change their underlying key material can register their `masterId` to an upgradeable proxy contract or multisig, allowing the controlling keys to be rotated at the contract layer without any protocol-level change. Finally, any rotation mechanism would require a timelock or similar delay to prevent an attacker who compromises a master key from silently redirecting deposits before the legitimate owner can respond — complexity that is better handled by the operator's own key management infrastructure.

In the event of a `masterId` collision (two `(address, salt)` pairs mapping to the same 4-byte `masterId`), the second registration reverts with `MasterIdCollision`. The caller can retry with a different valid salt. The probability of such a collision (and the resulting need to regrind another salt) is less than 0.1% even if 4 million masterId's have already been registered.

## Registration Proof of Work

Registration requires a 32-bit proof of work to make **targeted collisions against a chosen `masterId`** computationally expensive.

The registration hash is computed as:

```
registrationHash = keccak256(abi.encodePacked(msg.sender, salt))
```

The first 4 bytes of `registrationHash` MUST be zero:

```
require(bytes4(registrationHash[0:4]) == 0x00000000)  // 32-bit PoW
masterId = bytes4(registrationHash[4:8])
```

This requires the caller to grind ~2^32 salt values to find a valid registration. If the first 4 bytes are not zero, the call reverts with `ProofOfWorkFailed`.

This proof of work is intended to make it expensive for an attacker who sees a pending registration transaction to compute a different `(attackerAddress, salt)` pair that lands on the same `masterId` and gets mined first. With a 4-byte `masterId` and a 32-bit proof-of-work requirement, that targeted attack costs ~2^64 work.

## User Tag Derivation (Offchain)

The `userTag` is an opaque 6-byte value generated offchain by the operator. The protocol does not interpret or validate it — all values including `0x000000000000` are valid. It exists solely so the operator can attribute deposits to specific users via the two-hop `Transfer` events described below.

Operators maintain their own internal mapping `{internalUserId -> virtualAddress}`. No onchain transaction is needed to create a new deposit address.

## Worked Example

An exchange with master address `0xABCD...1234` registers with a salt that satisfies the 32-bit PoW:

* `registrationHash = keccak256(abi.encodePacked(0xABCD...1234, salt))`
* `registrationHash[0:4] == 0x00000000` (PoW satisfied)
* `masterId = bytes4(registrationHash[4:8])` -> e.g. `0x07A3B1C2`
* For customer #103048, the exchange derives a `userTag` -> e.g. `0xD4E5A7C3F19E`

```
Virtual address = 0x07A3B1C2  FDFDFDFDFDFDFDFDFDFD  D4E5A7C3F19E
                  ^^^^^^^^    ^^^^^^^^^^^^^^^^^^^^  ^^^^^^^^^^^^
                  masterId     magic (10)           userTag (6)
```

## Registry Precompile

Virtual address resolution requires a registry that maps `masterId -> masterAddress`. This is managed through a new precompile deployed at `0xFDC0000000000000000000000000000000000000`.

The registry MUST maintain the following mapping constraints:

* each `masterId` maps to at most one registered master address (one-to-one from `masterId`)
* multiple `masterId`s MAY map to the same master address (many-to-one)

This many-to-one design allows a single underlying wallet to register multiple `masterId`s (e.g. with different salts).

A **valid master address** MUST satisfy TIP-20 recipient safety constraints:

* MUST NOT be `address(0)`
* MUST NOT itself match the virtual-address format (`VIRTUAL_MAGIC` at bytes `[4:14]`)
* MUST NOT be a TIP-20 token address (`0x20c000....` at bytes `[0:12]`)

### Registry Storage Layout

Each `masterId` maps to a single 32-byte storage slot:

```
slot = keccak256(abi.encode(masterId, REGISTRY_SLOT))
value = masterType | reserved   | masterAddress
        ^^^^^^^^^^   ^^^^^^^^     ^^^^^^^^^^^
        1 byte       11 bytes     20 bytes
```

Here `REGISTRY_SLOT` means the storage slot of the `mapping(bytes4 => bytes32)` used to store registry entries, following standard Solidity mapping layout.

| Field | Bytes | Description |
|-------|-------|-------------|
| `masterType` | 1 | Type discriminator for future extensibility. MUST be `0x00` in this version. |
| `reserved` | 11 | Reserved for future use. MUST be zeroed. |
| `masterAddress` | 20 | The registered master address for this `masterId`. `address(0)` if unregistered. |

This layout packs all metadata for a `masterId` into a single storage slot, enabling one SLOAD during transfer-path resolution.

### Interface

```solidity
interface IAddressRegistry {
    // ──────────────────── Events ────────────────────

    /// @notice Emitted when a new master is registered.
    event MasterRegistered(
        bytes4 indexed masterId,
        address indexed masterAddress
    );

    // ──────────────────── Errors ────────────────────

    /// @notice The computed masterId is already registered to a different address.
    error MasterIdCollision();

    /// @notice The caller/new master address is invalid for virtual forwarding.
    error InvalidMasterAddress();

    /// @notice The registration hash does not satisfy the 32-bit proof-of-work requirement.
    error ProofOfWorkFailed();

    /// @notice The virtual address has a valid format but its masterId is not registered.
    error VirtualAddressUnregistered();

    // ──────────────── Registration ──────────────────

    /// @notice Registers msg.sender as a virtual address master.
    /// @dev The registration hash is keccak256(abi.encodePacked(msg.sender, salt)).
    ///      The first 4 bytes of the hash MUST be zero (32-bit proof of work).
    ///      masterId is derived from bytes [4:8] of the registration hash.
    ///      Reverts with ProofOfWorkFailed if the first 4 bytes are not zero.
    ///      Reverts with InvalidMasterAddress if msg.sender is not a valid master address.
    ///      Reverts with MasterIdCollision if the derived masterId is already taken
    ///      by a different address. On collision, the caller can retry with a different salt.
    ///      The same address MAY register multiple masterIds using different salts.
    /// @param salt Caller-chosen salt for masterId derivation. Must satisfy 32-bit PoW.
    /// @return masterId The derived master identifier.
    function registerVirtualMaster(bytes32 salt) external returns (bytes4 masterId);

    // ────────────────── Queries ─────────────────────

    /// @notice Returns the registered master address for a given masterId, or address(0) if unregistered.
    function getMaster(bytes4 masterId) external view returns (address);

    /// @notice Resolves a transfer recipient using TIP-1022 execution semantics.
    ///         For non-virtual addresses, returns `to` unchanged.
    ///         For virtual addresses, returns the registered master or reverts with
    ///         VirtualAddressUnregistered.
    function resolveRecipient(address to) external view returns (address effectiveRecipient);

    /// @notice Resolves a virtual address to its registered master.
    ///         Returns address(0) if the address does not match the virtual-address format.
    ///         Returns address(0) if the masterId is not registered.
    function resolveVirtualAddress(address virtualAddr) external view returns (address master);

    /// @notice Returns true if the address matches the virtual-address format.
    function isVirtualAddress(address addr) external pure returns (bool);

    /// @notice Decodes a virtual address into its components.
    /// @return isVirtual True if the address matches the virtual-address format.
    /// @return masterId The 4-byte master identifier (zero if not virtual).
    /// @return userTag The 6-byte user tag (zero if not virtual).
    function decodeVirtualAddress(address addr)
        external pure returns (bool isVirtual, bytes4 masterId, bytes6 userTag);
}
```

### Constants

| Name | Value | Description |
|------|-------|-------------|
| `VIRTUAL_MAGIC` | `0xFDFDFDFDFDFDFDFDFDFD` | 10-byte magic value identifying virtual addresses |
| `REGISTRY_ADDRESS` | `0xFDC0000000000000000000000000000000000000` | Precompile address for the virtual-address registry |

## Transfer Path Modification

The following existing TIP-20 entrypoints are modified to resolve the `to` (recipient) address before crediting:

* `transfer`
* `transferFrom`
* `transferWithMemo`
* `transferFromWithMemo`
* `mint`
* `mintWithMemo`
* `systemTransferFrom`

The `from` address on `transferFrom`, `transferFromWithMemo`, and `systemTransferFrom` is **not** affected by TIP-1022 resolution.

### Resolution Logic

```text
function resolveRecipient(to: address) -> address:
    // Check bytes [4:14] against VIRTUAL_MAGIC
    if to[4:14] != VIRTUAL_MAGIC:
        return to

    masterId = to[0:4]
    master = registry.getMaster(masterId)

    if master == address(0):
        revert VirtualAddressUnregistered()

    return master
```

### Standard Transfer Entrypoints

For `transfer`, `transferFrom`, `transferWithMemo`, `transferFromWithMemo`, and `systemTransferFrom`:

1. **Resolve recipient**: compute `effectiveRecipient = resolveRecipient(to)`. If `to` is not virtual, `effectiveRecipient = to`.
2. **Token-level sender check**: apply the standard TIP-403 / TIP-1015 sender authorization rules.
3. **Token-level recipient check**: apply the standard TIP-403 / TIP-1015 recipient authorization rules to `effectiveRecipient`.
4. **Apply balance changes**: debit sender, credit `effectiveRecipient`.
5. **Emit events**: per **Event Emission** (two-hop `Transfer` if virtual, single `Transfer` otherwise).

If any step reverts, the enclosing TIP-20 operation MUST revert atomically with no balance changes and no events.

### Mint Entrypoints

For `mint` and `mintWithMemo`:

1. **Resolve recipient**: compute `effectiveRecipient = resolveRecipient(to)`. If `to` is not virtual, `effectiveRecipient = to`.
2. **Token-level mint-recipient check**: apply the standard TIP-1015 mint-recipient authorization rules to `effectiveRecipient`.
3. **Apply balance changes**: credit `effectiveRecipient`.
4. **Emit events**: per **Event Emission**.

If any step reverts, the enclosing TIP-20 operation MUST revert atomically with no balance changes and no events.

### Authorization Semantics

TIP-1022 does not introduce new authorization logic in TIP-403 itself. Instead, TIP-20 transfer and mint logic MUST resolve virtual recipient addresses before invoking the existing TIP-403 / TIP-1015 checks.

Concretely, for any TIP-20 entrypoint covered by TIP-1022:

1. Compute `effectiveRecipient = resolveRecipient(to)`.
2. Apply the existing sender / recipient / mint-recipient authorization rules to `effectiveRecipient`, not the literal virtual address.

This preserves view/execution symmetry with the TIP-20 authorization path defined by TIP-1015: any internal TIP-20 helper such as `isTransferAuthorized(from, to)` MUST evaluate recipient authorization against the resolved master address when `to` is virtual.

`balanceOf(virtualAddress)` remains literal and MUST continue to return 0.

Contracts or integrators that need explicit resolution behavior outside the TIP-20 transfer path MAY call `resolveRecipient` on the registry.

## Event Emission

TIP-1022 does **not** introduce new transfer-path events. The registry precompile emits `MasterRegistered`, but forwarding itself is represented using **two-hop standard `Transfer` events**: one hop showing funds arriving at the virtual address, and a second hop showing funds moving from the virtual address to the resolved master. Using standard `Transfer` events (rather than a new event type) preserves compatibility with existing indexers, block explorers, and wallets that already understand TIP-20 / ERC-20 `Transfer` events — no custom integration is required to track virtual address deposits.

For transfers where the recipient is **not** a virtual address, event emission is unchanged from standard TIP-20 behavior — a single `Transfer(sender, to, amount)`.

### Deposit Forwarding (Inbound)

When a transfer targets a virtual address (`to` is virtual), the precompile MUST emit two `Transfer` events in sequence:

1. `Transfer(sender, virtualAddress, amount)` — shows funds arriving at the virtual address
2. `Transfer(virtualAddress, masterAddress, amount)` — shows funds forwarding to the master

The actual balance change is applied only to `masterAddress`. The virtual address never holds a balance; the first `Transfer` event is a logical representation of deposit attribution, not a real balance credit.

Indexers that need deposit attribution SHOULD watch for pairs of `Transfer` events within the same transaction where the intermediate address matches the virtual-address format. The `userTag` can then be extracted from the virtual address to identify the depositor.

### Entrypoint-Specific Event Ordering

* `transfer`, `transferFrom`, `systemTransferFrom`:
  1. `Transfer(sender, virtualAddress, amount)`
  2. `Transfer(virtualAddress, masterAddress, amount)`

* `transferWithMemo`, `transferFromWithMemo`:
  1. `Transfer(sender, virtualAddress, amount)`
  2. `TransferWithMemo(sender, virtualAddress, amount, memo)`
  3. `Transfer(virtualAddress, masterAddress, amount)`

* `mint`:
  1. `Transfer(address(0), virtualAddress, amount)`
  2. `Mint(virtualAddress, amount)`
  3. `Transfer(virtualAddress, masterAddress, amount)`

* `mintWithMemo`:
  1. `Transfer(address(0), virtualAddress, amount)`
  2. `TransferWithMemo(address(0), virtualAddress, amount, memo)`
  3. `Mint(virtualAddress, amount)`
  4. `Transfer(virtualAddress, masterAddress, amount)`

## Self-Forwarding

If the registered master sends tokens to one of its own virtual addresses, the transfer resolves back to the master, effectively a transfer to self. The standard TIP-20 self-transfer semantics apply (no net balance change). The two-hop `Transfer` events are still emitted: `Transfer(master, virtualAddress, amount)` followed by `Transfer(virtualAddress, master, amount)`. Indexers SHOULD NOT interpret this as net inflow when `from == masterAddress` in the first hop.

## Interaction with TIP-403

Virtual address resolution happens **before** TIP-403 / TIP-1015 authorization checks. Policy evaluation uses the resolved `masterAddress`, not the literal virtual address.

* If the **master address** is not authorized to receive the token, transfers to any of its virtual addresses revert.
* If the **sender** is not authorized to send the token, the transfer reverts.
* Policies configured on individual virtual addresses are ignored by the TIP-20 transfer path because virtual addresses have no independent canonical TIP-20 balance.

### Rejection of Virtual Addresses in Policy Operations

TIP-403 operations that accept addresses as policy members MUST reject virtual addresses rather than accepting them silently.

Implementations SHOULD use a clear, informative error indicating that virtual addresses are aliases for TIP-20 forwarding and are not valid literal policy subjects.

Rejecting these operations avoids the footgun where an operator configures policy on the virtual alias they see in logs or explorers instead of on the resolved master address that actually holds the funds.

## Interaction with Account-Level Features

* **`balanceOf(virtualAddress)`**: Always returns 0. Virtual addresses do not hold balances.
* **Nonce / transaction origination**: A contract or EOA whose address matches the virtual-address format can still exist and can still originate ordinary EVM transactions. TIP-1022 resolution applies only to the `to` field in TIP-20 precompile calls, not to transaction senders.

## Security Considerations

### 4-Byte `masterId` and 32-Bit Registration PoW

A 4-byte `masterId` would be too small if its security relied only on raw namespace size. TIP-1022 does **not** rely on that. Instead, security comes from the combination of:

* a 4-byte `masterId`, and
* a 32-bit proof-of-work requirement on registration

An attacker who sees a pending registration transaction and wants to steal that `masterId` must compute a different `(attackerAddress, salt)` pair that:

1. satisfies the 32-bit proof-of-work requirement, and
2. lands on the same 4-byte `masterId`

That targeted attack costs roughly 2^64 work. Further, because registration requires proof-of-work grinding, deployment will typically happen via dedicated tooling or a managed service that:

* performs the proof-of-work search,
* submits the registration transaction, and
* waits for confirmation or revert before the operator routes value through the resulting master ID.

This does not eliminate the residual collision-risk entirely, but it substantially reduces the practical chance that an operator incorrectly believes they control a master ID that was actually registered first by an attacker.

### Why the Magic Bytes Are in the Middle

The middle `VIRTUAL_MAGIC` layout is a deliberate usability tradeoff:

* it leaves the first 4 bytes available for `masterId`
* it leaves the last 6 bytes available for `userTag`
* it avoids spending the most visually important bytes of the address on static marker data

This improves address comparison in UIs while still keeping a large reserved pattern that is highly unlikely to appear accidentally. We believe this layout is superior to the other permutations in terms of the prospect of address poisoning attacks (see below).

### Contracts and EOAs Matching the Virtual Format

A sufficiently resourced adversary could, in principle, grind a CREATE2 deployment or private key so that a contract or EOA lands at an address matching the virtual-address format in a `masterID` controlled by the adversary. We view this as unlikely in practice because the address must match a 10-byte fixed magic value in the middle of the address, while targeted theft of a specific registered namespace also requires colliding the 4-byte `masterId` under the registration proof-of-work design (i.e., 14 bytes totally).

A stronger global reservation mechanism for problematic address ranges may still be desirable in the future.

### Policy Configuration on Virtual Addresses

Virtual addresses are forwarding aliases, not canonical TIP-20 holders. Using them directly in policy configuration is misleading and dangerous because the TIP-20 transfer path evaluates policies against the resolved master address.

Accordingly, TIP-403 configuration operations SHOULD reject virtual addresses with explicit errors rather than accepting them.

***

## Risks and Limitations

### Address Poisoning and UI Confusion

TIP-1022 still introduces a recognizable structured address format. Wallets, block explorers, and operational tooling that truncate addresses SHOULD display enough of the address to distinguish both the `masterId` and the `userTag`; ideally they SHOULD show the full address.

### Non-TIP-20 Token Loss

TIP-1022 forwarding applies exclusively to TIP-20 precompile operations. Non-TIP-20 tokens (e.g. ERC-20 contracts deployed on Tempo) transferred to a virtual address are credited to the literal virtual address by the ERC-20 contract and are irrecoverable: no recovery mechanism is defined here.

This risk is mitigated by the strong incentives for token issuers to use TIP-20 on Tempo (gas-payment eligibility, access to the payment lane, and policy support), but it remains a limitation of this design.

### Non-TIP-20 Protocol Positions Minted to Virtual Addresses

TIP-1022 changes only the TIP-20 transfer and mint entrypoints listed in this document. It does not change other protocol logic that accepts an address parameter and records ownership against that literal address.

This creates an edge case for protocols that mint LP shares, receipt tokens, or other redeemable positions to a user-supplied to address. If such a protocol later requires the recorded holder address to burn, redeem, or withdraw, a position minted to a virtual address can become stranded even though the corresponding master account controls that virtual namespace. The Fee AMM is one example of this pattern: LP shares minted can be mited to a virtual address, but are then permanently unburnable since `burn` checks that `msg_sender==lp_address`.

In short, virtual-address forwarding is only defined for the TIP-20 paths enumerated by TIP-1022; other protocols remain literal-address systems unless they explicitly say otherwise.

### Externally-Triggerable Revert on Unregistered Virtual Addresses

TIP-1022 introduces a recipient-dependent revert: if the `to` address matches the virtual-address format but its `masterId` is not registered, the transfer reverts with `VirtualAddressUnregistered`. This is the first TIP-20 revert condition that an untrusted recipient address can induce — prior to TIP-1022, transfers could only revert due to sender-side conditions (insufficient balance, authorization failure).

Contracts that perform batch transfers in a single transaction (e.g. payroll, airdrop, or distribution contracts) SHOULD validate recipient addresses before execution or wrap individual transfers in try/catch to prevent a single unregistered virtual address from reverting the entire batch.

### Contracts and EOAs at virtual addresses

It is theoretically possible to deploy a contract or control an EOA whose address matches `VIRTUAL_MAGIC`, including by grinding CREATE2 salts or private keys. Such addresses can still exist and originate ordinary EVM transactions, but we consider this unlikely in practice because targeting the 10-byte `VIRTUAL_MAGIC` requires roughly 2^80 work, with additional cost for targeted collisions against registered virtual namespaces.

***

# Invariants

## Core Invariants

1. **No fund loss**: A TIP-20 transfer to a virtual address MUST either credit the registered master's balance by exactly the transfer amount, or revert. Funds MUST NOT be credited to the virtual address itself or lost.

2. **Revert on unregistered**: A transfer to an address matching the virtual-address format whose `masterId` is not registered MUST revert. It MUST NOT credit any account.

3. **Balance consistency**: After a successful virtual-forwarded transfer of amount `X`, `balanceOf(master)` MUST have increased by exactly `X`.

4. **Zero-balance invariant**: For every virtual address, `balanceOf(virtualAddress)` MUST equal 0 from T3 activation onwards. Pre-T3, the TIP-20 precompile does not perform virtual-address resolution, so a transfer targeting an address that matches the virtual format will credit the literal address. Such pre-T3 balances are stranded (no party can claim them) and do not violate this invariant, which applies only to the T3-and-later transfer path. The probability of anyone controlling a private key for such an address is negligible.

5. **Event consistency**: For virtual-forwarded entrypoints, the precompile MUST emit two `Transfer` events: `Transfer(sender, virtualAddress, amount)` followed by `Transfer(virtualAddress, masterAddress, amount)`. `TransferWithMemo` events MUST immediately follow their matching `Transfer` and MUST use `virtualAddress` as the recipient to preserve deposit attribution. `Mint` events MUST use `virtualAddress`.

6. **Non-virtual path unaffected**: Transfers to addresses that do not match the virtual-address format MUST behave identically to pre-TIP-1022 semantics, with no registry lookup.

7. **Deterministic masterId**: Given `registrationHash = keccak256(abi.encodePacked(registrationAddress, salt))`, the first 4 bytes of `registrationHash` MUST be zero, and `masterId` MUST equal `bytes4(registrationHash[4:8])`, where `registrationAddress` is the address that called `registerVirtualMaster()` and `salt` is the caller-supplied salt. If the PoW check fails, registration MUST revert with `ProofOfWorkFailed`. `masterId` MUST NOT depend on registration order or transaction ordering.

8. **Master ID uniqueness**: Each `masterId` MUST map to at most one registered master address. Multiple `masterId`s MAY map to the same master address.

9. **Atomic revert behavior**: If virtual resolution fails, the enclosing TIP-20 call MUST revert with no state changes and no events.

10. **View/execution symmetry**: TIP-20 authorization logic MUST evaluate recipient authorization against the resolved master address when `to` is virtual, matching execution-time recipient resolution semantics.

11. **Policy on master**: TIP-403 / TIP-1015 authorization for virtual-forwarded transfers and mints MUST check the resolved `masterAddress`. Policies set on individual virtual addresses MUST be ignored by the TIP-20 transfer path.

12. **Policy-operation rejection**: TIP-403 configuration operations that accept literal addresses as policy subjects or members MUST reject virtual addresses.
