<!--
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.
-->

# TIP20

## Abstract

TIP20 is a suite of precompiles that provide a built-in optimized token implementation in the core protocol. It extends the ERC-20 token standard with built-in functionality like memo fields and reward distribution.

## Motivation

All major stablecoins today use the ERC-20 token standard. While ERC-20 provides a solid foundation for fungible tokens, it lacks features critical for stablecoin issuers today such as memos, transfer policies, and rewards distribution. Additionally, since each ERC-20 token has its own implementation, integrators can't depend on consistent behavior across tokens.
TIP-20 extends ERC-20, building these features into precompiled contracts that anyone can permissionlessly deploy on Tempo. This makes token operations much more efficient, allows issuers to quickly set up on Tempo, and simplifies integrations since it ensures standardized behavior across tokens.
It also enables deeper integration with token-specific Tempo features like paying gas in stablecoins and payment lanes.

## Specification

TIP-20 tokens support standard fungible token operations such as transfers, mints, and burns. They also support transfers, mints, and burns with an attached 32-byte memo; a role-based access control system for token administrative operations; and a system for opt-in [reward distribution](/protocol/tip20-rewards/spec).

## TIP20

The core TIP-20 contract exposes standard ERC-20 functions for balances, allowances, transfers, and delegated transfers, and also adds:

* 32-byte memo support on transfers, mints, and burns.
* A `TIP20Roles` module for permissioned actions like issuing, pausing, unpausing, and burning blocked balances.
* Configuration options for currencies, quote tokens, and transfer policies.

The complete TIP20 interface is defined below:

```solidity
interface ITIP20 {
    // =========================================================================
    //                      ERC-20 standard functions
    // =========================================================================

    /// @notice Returns the name of the token
    /// @return The token name
    function name() external view returns (string memory);
    
    /// @notice Returns the symbol of the token
    /// @return The token symbol
    function symbol() external view returns (string memory);
    
    /// @notice Returns the number of decimals for the token
    /// @return Always returns 6 for TIP-20 tokens
    function decimals() external pure returns (uint8);
    
    /// @notice Returns the total amount of tokens in circulation
    /// @return The total supply of tokens
    function totalSupply() external view returns (uint256);
    
    /// @notice Returns the token balance of an account
    /// @param account The address to check the balance for
    /// @return The token balance of the account
    function balanceOf(address account) external view returns (uint256);
    
    /// @notice Transfers tokens from caller to recipient
    /// @param to The recipient address
    /// @param amount The amount of tokens to transfer
    /// @return True if successful
    function transfer(address to, uint256 amount) external returns (bool);
    
    /// @notice Returns the remaining allowance for a spender
    /// @param owner The token owner address
    /// @param spender The spender address
    /// @return The remaining allowance amount
    function allowance(address owner, address spender) external view returns (uint256);
    
    /// @notice Approves a spender to spend tokens on behalf of caller
    /// @param spender The address to approve
    /// @param amount The amount to approve
    /// @return True if successful
    function approve(address spender, uint256 amount) external returns (bool);
    
    /// @notice Transfers tokens from one address to another using allowance
    /// @param from The sender address
    /// @param to The recipient address
    /// @param amount The amount to transfer
    /// @return True if successful
    function transferFrom(address from, address to, uint256 amount) external returns (bool);

    /// @notice Mints new tokens to an address (requires ISSUER_ROLE)
    /// @param to The recipient address
    /// @param amount The amount of tokens to mint
    function mint(address to, uint256 amount) external;

    /// @notice Burns tokens from caller's balance (requires ISSUER_ROLE)
    /// @param amount The amount of tokens to burn
    function burn(uint256 amount) external;

    // =========================================================================
    //                      TIP-20 extended functions
    // =========================================================================

    /// @notice Transfers tokens from caller to recipient with a memo
    /// @param to The recipient address
    /// @param amount The amount of tokens to transfer
    /// @param memo A 32-byte memo attached to the transfer
    function transferWithMemo(address to, uint256 amount, bytes32 memo) external;
    
    /// @notice Transfers tokens from one address to another with a memo using allowance
    /// @param from The sender address
    /// @param to The recipient address
    /// @param amount The amount to transfer
    /// @param memo A 32-byte memo attached to the transfer
    /// @return True if successful
    function transferFromWithMemo(address from, address to, uint256 amount, bytes32 memo) external returns (bool);
    
    /// @notice Mints new tokens to an address with a memo (requires ISSUER_ROLE)
    /// @param to The recipient address
    /// @param amount The amount of tokens to mint
    /// @param memo A 32-byte memo attached to the mint
    function mintWithMemo(address to, uint256 amount, bytes32 memo) external;
    
    /// @notice Burns tokens from caller's balance with a memo (requires ISSUER_ROLE)
    /// @param amount The amount of tokens to burn
    /// @param memo A 32-byte memo attached to the burn
    function burnWithMemo(uint256 amount, bytes32 memo) external;
    
    /// @notice Burns tokens from a blocked address (requires BURN_BLOCKED_ROLE)
    /// @param from The address to burn tokens from (must be unauthorized by transfer policy)
    /// @param amount The amount of tokens to burn
    function burnBlocked(address from, uint256 amount) external;
    
    /// @notice Returns the quote token used for DEX pairing
    /// @return The quote token address
    function quoteToken() external view returns (ITIP20);
    
    /// @notice Returns the next quote token staged for update
    /// @return The next quote token address (zero if none staged)
    function nextQuoteToken() external view returns (ITIP20);
    
    /// @notice Returns the currency identifier for this token
    /// @return The currency string
    function currency() external view returns (string memory);
    
    /// @notice Returns whether the token is currently paused
    /// @return True if paused, false otherwise
    function paused() external view returns (bool);
    
    /// @notice Returns the maximum supply cap for the token
    /// @return The supply cap (checked on mint operations)
    function supplyCap() external view returns (uint256);
    
    /// @notice Returns the current transfer policy ID from TIP-403 registry
    /// @return The transfer policy ID
    function transferPolicyId() external view returns (uint64);
    
    // =========================================================================
    //                            Admin Functions 
    // =========================================================================
    
    /// @notice Pauses the contract, blocking transfers (requires PAUSE_ROLE)
    function pause() external;
    
    /// @notice Unpauses the contract, allowing transfers (requires UNPAUSE_ROLE)
    function unpause() external;
    
    /// @notice Changes the transfer policy ID (requires DEFAULT_ADMIN_ROLE)
    /// @param newPolicyId The new policy ID from TIP-403 registry
    /// @dev Validates that the policy exists using TIP403Registry.policyExists().
    /// Built-in policies (ID 0 = always-reject, ID 1 = always-allow) are always valid.
    /// For custom policies (ID >= 2), the policy must exist in the TIP-403 registry.
    /// Reverts with InvalidTransferPolicyId if the policy does not exist.
    function changeTransferPolicyId(uint64 newPolicyId) external;
    
    /// @notice Stages a new quote token for update (requires DEFAULT_ADMIN_ROLE)
    /// @param newQuoteToken The new quote token address
    function setNextQuoteToken(ITIP20 newQuoteToken) external;
    
    /// @notice Completes the quote token update process (requires DEFAULT_ADMIN_ROLE)
    function completeQuoteTokenUpdate() external;
    
    /// @notice Sets the maximum supply cap (requires DEFAULT_ADMIN_ROLE)
    /// @param newSupplyCap The new supply cap (cannot be less than current supply)
    function setSupplyCap(uint256 newSupplyCap) external;
    
    // =========================================================================
    //                            Role Management
    // =========================================================================
    
    /// @notice Returns the BURN_BLOCKED_ROLE constant
    /// @return keccak256("BURN_BLOCKED_ROLE")
    function BURN_BLOCKED_ROLE() external view returns (bytes32);
    
    /// @notice Returns the ISSUER_ROLE constant
    /// @return keccak256("ISSUER_ROLE")
    function ISSUER_ROLE() external view returns (bytes32);
    
    /// @notice Returns the PAUSE_ROLE constant
    /// @return keccak256("PAUSE_ROLE")
    function PAUSE_ROLE() external view returns (bytes32);
    
    /// @notice Returns the UNPAUSE_ROLE constant
    /// @return keccak256("UNPAUSE_ROLE")
    function UNPAUSE_ROLE() external view returns (bytes32);
    
    /// @notice Grants a role to an account (requires role admin)
    /// @param role The role to grant (keccak256 hash)
    /// @param account The account to grant the role to
    function grantRole(bytes32 role, address account) external;
    
    /// @notice Revokes a role from an account (requires role admin)
    /// @param role The role to revoke (keccak256 hash)
    /// @param account The account to revoke the role from
    function revokeRole(bytes32 role, address account) external;
    
    /// @notice Allows an account to remove a role from itself
    /// @param role The role to renounce (keccak256 hash)
    function renounceRole(bytes32 role) external;
    
    /// @notice Changes the admin role for a specific role (requires current role admin)
    /// @param role The role whose admin is being changed
    /// @param adminRole The new admin role
    function setRoleAdmin(bytes32 role, bytes32 adminRole) external;
    
    // =========================================================================
    //                     EIP-2612 Permit (TIP-1004)
    // =========================================================================

    /// @notice Approves a spender via an off-chain signature (EIP-2612)
    /// @param owner The token owner who signed the permit
    /// @param spender The address being approved
    /// @param value The allowance amount
    /// @param deadline The timestamp after which the signature expires
    /// @param v ECDSA recovery byte (must be 27 or 28; 0/1 is not normalized)
    /// @param r ECDSA signature component
    /// @param s ECDSA signature component
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    /// @notice Returns the current nonce for an owner (incremented on each permit)
    /// @param owner The address to query
    /// @return The current nonce
    function nonces(address owner) external view returns (uint256);

    /// @notice Returns the EIP-712 domain separator for this token
    /// @return The domain separator hash (computed dynamically using block.chainid)
    function DOMAIN_SEPARATOR() external view returns (bytes32);

    // =========================================================================
    //                            System Functions
    // =========================================================================
    
    /// @notice System-level transfer function (restricted to precompiles)
    /// @param from The sender address
    /// @param to The recipient address
    /// @param amount The amount to transfer
    /// @return True if successful
    function systemTransferFrom(address from, address to, uint256 amount) external returns (bool);
    
    /// @notice Pre-transaction fee transfer (restricted to precompiles)
    /// @param from The account to charge fees from
    /// @param amount The fee amount
    function transferFeePreTx(address from, uint256 amount) external;
    
    /// @notice Post-transaction fee handling (restricted to precompiles)
    /// @param to The account to refund
    /// @param refund The refund amount
    /// @param actualUsed The actual fee used
    function transferFeePostTx(address to, uint256 refund, uint256 actualUsed) external;


    // =========================================================================
    //                                Events
    // =========================================================================

    /// @notice Emitted when a new allowance is set by `owner` for `spender`
    /// @param owner The account granting the allowance
    /// @param spender The account being approved to spend tokens
    /// @param amount The new allowance amount
    event Approval(address indexed owner, address indexed spender, uint256 amount);

    /// @notice Emitted when tokens are burned from an address
    /// @param from The address whose tokens were burned
    /// @param amount The amount of tokens that were burned
    event Burn(address indexed from, uint256 amount);

    /// @notice Emitted when tokens are burned from a blocked address
    /// @param from The blocked address whose tokens were burned
    /// @param amount The amount of tokens that were burned
    event BurnBlocked(address indexed from, uint256 amount);

    /// @notice Emitted when new tokens are minted to an address
    /// @param to The address receiving the minted tokens
    /// @param amount The amount of tokens that were minted
    event Mint(address indexed to, uint256 amount);

    /// @notice Emitted when a new quote token is staged for this token
    /// @param updater The account that staged the new quote token
    /// @param nextQuoteToken The quote token that has been staged
    event NextQuoteTokenSet(address indexed updater, ITIP20 indexed nextQuoteToken);

    /// @notice Emitted when the pause state of the token changes
    /// @param updater The account that changed the pause state
    /// @param isPaused The new pause state; true if paused, false if unpaused
    event PauseStateUpdate(address indexed updater, bool isPaused);

    /// @notice Emitted when the quote token update process is completed
    /// @param updater The account that completed the quote token update
    /// @param newQuoteToken The new quote token that has been set
    event QuoteTokenUpdate(address indexed updater, ITIP20 indexed newQuoteToken);

    /// @notice Emitted when a holder sets or updates their reward recipient address
    /// @param holder The token holder configuring the recipient
    /// @param recipient The address that will receive claimed rewards
    event RewardRecipientSet(address indexed holder, address indexed recipient);

    /// @notice Emitted when a reward distribution is scheduled
    /// @param funder The account funding the reward distribution
    /// @param amount The total amount of tokens allocated to the reward
    event RewardDistributed(
        address indexed funder,
        uint256 amount,
    );

    /// @notice Emitted when the token's supply cap is updated
    /// @param updater The account that updated the supply cap
    /// @param newSupplyCap The new maximum total supply
    event SupplyCapUpdate(address indexed updater, uint256 indexed newSupplyCap);

    /// @notice Emitted for all token movements, including mints and burns
    /// @param from The address sending tokens (address(0) for mints)
    /// @param to The address receiving tokens (address(0) for burns)
    /// @param amount The amount of tokens transferred
    event Transfer(address indexed from, address indexed to, uint256 amount);

    /// @notice Emitted when the transfer policy ID is updated
    /// @param updater The account that updated the transfer policy
    /// @param newPolicyId The new transfer policy ID from the TIP-403 registry
    event TransferPolicyUpdate(address indexed updater, uint64 indexed newPolicyId);

    /// @notice Emitted when a transfer, mint, or burn is performed with an attached memo
    /// @param from The address sending tokens (address(0) for mints)
    /// @param to The address receiving tokens (address(0) for burns)
    /// @param amount The amount of tokens transferred
    /// @param memo The 32-byte memo associated with this movement
    event TransferWithMemo(
        address indexed from,
        address indexed to,
        uint256 amount,
        bytes32 indexed memo
    );

    /// @notice Emitted when the membership of a role changes for an account
    /// @param role The role being granted or revoked
    /// @param account The account whose membership was changed
    /// @param sender The account that performed the change
    /// @param hasRole True if the role was granted, false if it was revoked
    event RoleMembershipUpdated(
        bytes32 indexed role,
        address indexed account,
        address indexed sender,
        bool hasRole
    );

    /// @notice Emitted when the admin role for a role is updated
    /// @param role The role whose admin role was changed
    /// @param newAdminRole The new admin role for the given role
    /// @param sender The account that performed the update
    event RoleAdminUpdated(
        bytes32 indexed role,
        bytes32 indexed newAdminRole,
        address indexed sender
    );

    // =========================================================================
    //                                Errors
    // =========================================================================

    /// @notice The token operation is blocked because the contract is currently paused
    error ContractPaused();

    /// @notice The permit signature has expired (block.timestamp > deadline)
    error PermitExpired();

    /// @notice The recovered signer does not match the permit owner
    error InvalidSignature();

    /// @notice The spender does not have enough allowance for the attempted transfer
    error InsufficientAllowance();

    /// @notice The account does not have the required token balance for the operation
    /// @param currentBalance The current balance of the account
    /// @param expectedBalance The required balance for the operation to succeed
    /// @param token The address of the token contract
    error InsufficientBalance(uint256 currentBalance, uint256 expectedBalance, address token);

    /// @notice The provided amount is zero or otherwise invalid for the attempted operation
    error InvalidAmount();

    /// @notice The provided currency identifier is invalid or unsupported
    error InvalidCurrency();

    /// @notice The specified quote token is invalid, incompatible, or would create a circular reference
    error InvalidQuoteToken();

    /// @notice The recipient address is not a valid destination for this operation
    ///         (for example, another TIP-20 token contract)
    error InvalidRecipient();

    /// @notice The specified transfer policy ID does not exist in the TIP-403 registry
    error InvalidTransferPolicyId();

    /// @notice The new supply cap is invalid, for example lower than the current total supply
    error InvalidSupplyCap();

    /// @notice A rewards operation was attempted when no opted-in supply exists
    error NoOptedInSupply();

    /// @notice The configured transfer policy denies authorization for the sender or recipient
    error PolicyForbids();

    /// @notice The attempted operation would cause total supply to exceed the configured supply cap
    error SupplyCapExceeded();

    /// @notice The caller does not have the required role or permission for this operation
    error Unauthorized();

}
```

:::warning
When interacting with precompiles, **always use the provided ABI** rather than reading directly from storage slots. Direct storage access may lead to undefined behavior.
:::

## Memos

Memo functions `transferWithMemo`, `transferFromWithMemo`, `mintWithMemo`, and `burnWithMemo` behave like their ERC-20 equivalents but additionally emit memo data in dedicated events. The memo is always a fixed 32-byte field. Callers should pack shorter strings or identifiers directly into this field, and use hashes or external references when the underlying payload exceeds 32 bytes.

## TIP-403 Transfer Policies

All operations that move tokens: `transfer`, `transferFrom`, `transferWithMemo`, `transferFromWithMemo`, `mint`, `burn`, `mintWithMemo`, and `burnWithMemo` — enforce the token’s configured TIP-403 transfer policy.

Internally, this is implemented via a `transferAuthorized` modifier that:

* Calls `TIP403_REGISTRY.isAuthorized(transferPolicyId, from)` for the sender.
* Calls `TIP403_REGISTRY.isAuthorized(transferPolicyId, to)` for the recipient.

Both checks must return `true`, otherwise the call reverts with `PolicyForbids`.
Reward operations (`distributeReward`, `setRewardRecipient`, `claimRewards`) also perform the same TIP-403 authorization checks before moving any funds.

## Invalid Recipient Protection

TIP-20 tokens cannot be sent to other TIP-20 token contract addresses. The implementation uses a `validRecipient` guard that rejects recipients whose address is zero, or has the TIP-20 prefix (`0x20c000000000000000000000`).
Any attempt to transfer to a TIP-20 token address must revert with `InvalidRecipient`. This prevents accidental token loss by sending funds to token contracts instead of user accounts.

## Currencies and Quote Tokens

Each TIP-20 token declares a currency identifier and a corresponding `quoteToken` used for pricing and routing in the Stablecoin DEX. Stablecoin currency identifiers should be [ISO 4217](https://www.iso.org/iso-4217-currency-codes.html) three-letter codes representing the underlying fiat currency (e.g., `"USD"`, `"EUR"`, `"GBP"`) — not the token's own symbol. The currency is set at token creation and **cannot be changed afterward**. **Only tokens with `currency == "USD"` are eligible for paying transaction fees.** Tokens with `currency == "USD"` must pair with a USD-denominated TIP-20 token.

Updating the quote token occurs in two phases:

1. `setNextQuoteToken` stages a new quote token.
2. `completeQuoteTokenUpdate` finalizes the change.

The implementation must validate that the new quote token is a TIP-20 token, matches currency rules, and does not create circular quote-token chains.

:::note
While quote tokens can be changed, choose carefully as the update process requires careful coordination with the DEX.
:::

## Permit (TIP-1004)

TIP-20 tokens support [EIP-2612](https://eips.ethereum.org/EIPS/eip-2612) `permit`, added in the [T2 network upgrade](/protocol/upgrades/t2). A token owner signs an EIP-712 typed message off-chain authorizing a spender, and any third party can submit that signature on-chain — combining approve and action into a single transaction without the owner paying gas.

The `DOMAIN_SEPARATOR` is computed dynamically on every call using `block.chainid`, so it remains correct after a chain fork. Each owner has a monotonically increasing `nonce` to prevent replay. Only `v = 27` or `v = 28` is accepted; `v = 0` or `v = 1` is intentionally **not** normalized (see [TIP-1004](/protocol/tips/tip-1004) for rationale).

## Pause Controls

Pause controls `pause` and `unpause` govern all transfer operations and reward related flows. When paused, transfers and memo transfers halt, but administrative and configuration functions remain allowed. The `paused()` getter reflects the current state and must be checked by all affected entrypoints.

## TIP-20 Roles

TIP-20 uses a role-based authorization system. The main roles are:

* `ISSUER_ROLE`: controls minting and burning.
* `PAUSE_ROLE` / `UNPAUSE_ROLE`: controls the token’s paused state.
* `BURN_BLOCKED_ROLE`: allows burning balances belonging to addresses that fail TIP-403 authorization.

Roles are assigned and managed through `grantRole`, `revokeRole`, `renounceRole`, and `setRoleAdmin`, via the contract admin.

## System Functions

System level functions `systemTransferFrom`, `transferFeePreTx`, and `transferFeePostTx` are only callable by other Tempo protocol precompiles. These entrypoints power transaction fee collection, refunds, and internal accounting within the Fee AMM and Stablecoin DEX. They must not be callable by general contracts or users.

`transferFeePreTx` respects the token's pause state and will revert if the token is paused. However, `transferFeePostTx` is intentionally allowed to execute even when the token is paused. This ensures that a transaction which pauses the token can still complete successfully and receive its fee refund. Apart from this specific refund transfer, no other token transfers can occur after a pause event.

## Token Rewards Distribution

See [rewards distribution](/protocol/tip20-rewards/spec) for more information.

## TIP20Factory

The `TIP20Factory` contract is the canonical entrypoint for creating new TIP-20 tokens on Tempo. The factory derives deterministic deployment addresses using a caller-provided salt, combined with the caller's address, under a fixed 12-byte TIP-20 prefix. This ensures that every TIP-20 token exists at a predictable, collision-free address. The `TIP20Factory` precompile is deployed at `0x20Fc000000000000000000000000000000000000`.

Newly created TIP-20 addresses are deployed to a deterministic address derived from `TIP20_PREFIX || lowerBytes`, where:

* `TIP20_PREFIX` is the 12-byte prefix `20C000000000000000000000`
* `lowerBytes` is the highest 64 bits of `keccak256(msg.sender, salt)`

The first 1000 addresses (where `lowerBytes < 1000`) are reserved for protocol use and cannot be deployed to via the factory.

When creating a token, the factory performs several checks to guarantee consistency across the TIP-20 ecosystem:

* The specified Quote token must be a currently deployed TIP20.
* Tokens that specify their currency as USD must also specify a quote token that is denoted in USD.
* At deployment, the factory initializes defaults on the TIP-20:\
  `transferPolicyId = 1`, `supplyCap = type(uint128).max`, `paused = false`, and `totalSupply = 0`.
* The provided `admin` address receives `DEFAULT_ADMIN_ROLE`, enabling it to manage roles and token configurations.

The complete `TIP20Factory` interface is defined below:

```solidity
/// @title TIP-20 Factory Interface
/// @notice Deploys and initializes new TIP-20 tokens at deterministic addresses
interface ITIP20Factory {
    /// @notice Creates and deploys a new TIP-20 token
    /// @param name The token's ERC-20 name
    /// @param symbol The token's ERC-20 symbol
    /// @param currency The token's ISO 4217 currency code (e.g. "USD", "EUR"). Immutable after creation.
    /// @param quoteToken The TIP-20 quote token used for exchange pricing
    /// @param admin The address to receive DEFAULT_ADMIN_ROLE on the new token
    /// @param salt A unique salt for deterministic address derivation
    ///
    /// @return token The deployed TIP-20 token address
    /// @dev
    ///  - Computes the TIP-20 deployment address as TIP20_PREFIX || lowerBytes,
    ///    where lowerBytes is the highest 64 bits of keccak256(msg.sender, salt)
    ///  - Reverts with AddressReserved if lowerBytes < 1000
    ///  - Ensures the provided quote token is itself a valid TIP-20
    ///  - Enforces USD-denomination rules (USD tokens must use USD quote tokens)
    ///  - Initializes the token with default settings:
    ///         transferPolicyId = 1 (always-allow)
    ///         supplyCap        = type(uint128).max
    ///         paused           = false
    ///         totalSupply      = 0
    ///  - Grants DEFAULT_ADMIN_ROLE on the new token to `admin`
    ///  - Emits a {TokenCreated} event
    function createToken(
        string memory name,
        string memory symbol,
        string memory currency,
        ITIP20 quoteToken,
        address admin,
        bytes32 salt
    ) external returns (address token);

    // =========================================================================
    //                                Helpers
    // =========================================================================

    /// @notice Returns true if `token` is a valid TIP-20 address
    /// @param token The address to check
    /// @return True if the address is a well-formed TIP-20
    /// @dev Checks the TIP-20 prefix and verifies the token has code deployed
    function isTIP20(address token) external view returns (bool);

    /// @notice Computes the deterministic TIP-20 address for a given sender and salt
    /// @param sender The address that will call {createToken}
    /// @param salt The salt that will be passed to {createToken}
    /// @return token The TIP-20 address that would be deployed
    /// @dev Computes the address as TIP20_PREFIX || lowerBytes, where lowerBytes is
    ///      the highest 64 bits of keccak256(sender, salt), matching the factory deployment scheme.
    function getTokenAddress(address sender, bytes32 salt) external pure returns (address token);

    // =========================================================================
    //                                Events
    // =========================================================================

    /// @notice Emitted when a new TIP-20 token is created
    /// @param token The newly deployed TIP-20 address
    /// @param name The token name
    /// @param symbol The token symbol
    /// @param currency The token currency
    /// @param quoteToken The token's assigned quote token
    /// @param admin The address receiving DEFAULT_ADMIN_ROLE
    /// @param salt The salt used for deterministic address derivation
    event TokenCreated(
        address indexed token,
        string name,
        string symbol,
        string currency,
        ITIP20 quoteToken,
        address admin,
        bytes32 salt
    );

    // =========================================================================
    //                                Errors
    // =========================================================================

    /// @notice The computed address falls within the reserved range (lowerBytes < 1000)
    error AddressReserved();

    /// @notice The provided quote token address is invalid or not a TIP-20
    error InvalidQuoteToken();
}
```

## Invariants

* `totalSupply()` must always equal to the sum of all `balanceOf(account)` over all accounts.
* `totalSupply()` must always be `<= supplyCap`
* When `paused` is `true`, no functions that move tokens (`transfer`, `transferFrom`, memo variants, `systemTransferFrom`, `transferFeePreTx`, `distributeReward`, `setRewardRecipient`, `claimRewards`) can succeed.
* TIP20 tokens cannot be transferred to another TIP20 token contract address.
* `systemTransferFrom`, `transferFeePreTx`, and `transferFeePostTx` never change `totalSupply()`.
