Tempo: Initial Thoughts
Tempo is a new L1 optimized specifically for stablecoin payments. The chain processes payments for less than $0.001 per transaction, achieves sub-second finality, and implements native compliance, multi-currency gas payments, and passkey authentication.
We will walk through key parts of the technical architecture, key design decisions, and get you started building on Tempo. It is an exciting step forward in many ways.
Resources:
- Tempo Documentation - Complete technical documentation
- GitHub Repository - Open source implementation
- Testnet Faucet - Get testnet tokens
Core Features
Payment-First Architecture
Traditional blockchains treat all transactions equally. Tempo implements dedicated payment lanes directly into the protocol, recognizing that payment transactions have different requirements than smart contract execution.
The TIP-20 token standard (Tempo’s enhanced ERC-20) includes:
- Payment lanes: Segregated transaction pools for predictable throughput
- On-chain memos: Native reconciliation support with transaction metadata
- Built-in compliance: TIP-403 policy registry for shared KYC/AML rules
- Sub-block architecture: Parallel processing for higher throughput
// Send a payment with TIP-20 transfers
import { parseUnits } from 'viem'
import { client } from './viem.config'
const { receipt } = await client.token.transferSync({
amount: parseUnits('100', 6), // 100 tokens (6 decimals)
to: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEbb',
token: '0x20c0000000000000000000000000000000000001', // AlphaUSD
})
Multi-Currency Gas
Users pay gas in any supported stablecoin, while validators receive their preferred currency. A built-in Fee AMM automatically converts between stablecoins at market rates.
Signature Types
Tempo transactions support three signature types natively:
- Secp256k1: Standard Ethereum signatures
- P256: Passkey/WebAuthn signatures
- WebAuthn: Full passkey authentication with biometrics
import { Account, WebAuthnP256 } from 'tempo.ts/viem'
import { parseEther } from 'viem'
// 1. Create a new passkey credential
const credential = await WebAuthnP256.createCredential({
name: 'My App Account'
})
// 2. Instantiate account from credential
const account = Account.fromWebAuthnP256(credential)
// 3. Store public key for future use (recommended)
await store.set(credential.id, credential.publicKey)
// 4. Sign a transaction
const hash = await account.signTransaction({
to: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEbb',
value: parseEther('1.0'),
// ... other transaction fields
})
Implementation: crates/primitives/src/transaction/tempo_transaction.rs:28-38
Protocol-Level Account Abstraction
Tempo Transactions (Type 0x76) provide account abstraction features natively at the protocol level rather than through smart contracts.
Batched Transactions:
import { client } from './viem.config'
// Execute multiple operations atomically
const { address, hash, id } = await client.sendTransaction({
calls: [
{ to: tokenAddress, data: approveCalldata },
{ to: dexAddress, data: swapCalldata },
{ to: recipient, value: amount, data: transferCalldata }
]
// All execute atomically - succeed together or fail together
})
2D Nonce System for Parallelization:
import { client } from './viem.config'
// Send multiple transactions concurrently from same account
// First parallel sequence
await client.sendTransaction({
calls: [...],
nonceKey: 1n,
nonce: 0n,
})
// Second parallel sequence (can be in same block)
await client.sendTransaction({
calls: [...],
nonceKey: 2n,
nonce: 0n,
})
// Continue first sequence
await client.sendTransaction({
calls: [...],
nonceKey: 1n,
nonce: 1n,
})
Fee Sponsorship:
import { parseUnits } from 'viem'
import { privateKeyToAccount } from 'viem/accounts'
import { client } from './viem.config'
// Option 1: Local account sponsorship
const sponsorAccount = privateKeyToAccount('0x...')
const { receipt } = await client.token.transferSync({
amount: parseUnits('100', 6),
to: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEbb',
token: '0x20c0000000000000000000000000000000000001',
feePayer: sponsorAccount, // Sponsor pays the transaction fee
})
// Option 2: Relay-based sponsorship (requires withFeePayer transport)
const { receipt } = await client.token.transferSync({
amount: parseUnits('100', 6),
to: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEbb',
token: '0x20c0000000000000000000000000000000000001',
feePayer: true, // Use configured fee relay service
})
Scheduled Transactions:
import { client } from './viem.config'
// Transaction only valid in specific time window
await client.sendTransaction({
calls: [...],
validAfter: 1735689600, // Not before Jan 1, 2025
validBefore: 1767225600, // Not after Jan 1, 2026
})
Key Authorization Provisioning:
import { client } from './viem.config'
// Provision a new access key in the same transaction
await client.sendTransaction({
calls: [...],
keyAuthorization: {
keyType: 'p256', // or 'secp256k1', 'webauthn'
expiry: timestamp,
limits: [{ token: usdcAddress, limit: maxAmount }],
keyId: newKeyAddress
}
// Transaction signature verified with new key
})
Implementation: crates/primitives/src/transaction/tempo_transaction.rs:150-223
Architecture
Dual-Layer Design
Tempo separates execution and consensus into distinct layers:
Execution Layer: Reth
- Paradigm’s Ethereum client implementation
- Full EVM compatibility (Osaka hardfork target)
- Compatible with Solidity, Foundry, Hardhat
- Custom precompiles for payment features
Consensus Layer: Commonware Simplex
- Sub-second finality in normal conditions
- BLS12-381 threshold signatures
- Graceful degradation under network stress
- DKG for validator set changes
Source: https://github.com/commonwarexyz/monorepo
Integration: crates/commonware-node/src/lib.rs:1-192
Custom Precompiles
Payment-critical features are implemented as native Rust precompiles:
| Precompile | Address Range | Purpose |
|---|---|---|
| TIP20 | 0x20C0... |
Enhanced ERC-20 with payment lanes |
| TIP20Factory | 0x20FC000... |
Token creation and management |
| TIP403Registry | Fixed address | Compliance policy registry |
| AccountKeychain | Fixed address | Multi-key management + passkeys |
| StablecoinExchange | Fixed address | Native DEX for stablecoin swaps |
| TipFeeManager | Fixed address | Fee token selection and conversion |
| NonceManager | Fixed address | 2D nonce system management |
| ValidatorConfig | Fixed address | Validator configuration |
Implementation: crates/precompiles/src/lib.rs:77-111
Specification approach:
- Solidity reference:
docs/specs/src/*.sol - Rust production:
crates/precompiles/src/*/mod.rs - Cross-validated with Foundry fuzz testing
Performance Optimizations
1. ASM-Keccak (2-5x faster hashing)
- Assembly-optimized keccak256 using AVX2/SSE
- Critical for signature verification and storage operations
- Enabled by default:
bin/tempo/Cargo.toml:42
2. Jemalloc (~10% overall improvement)
- Facebook’s multi-threaded memory allocator
- Better fragmentation and cache locality
- Reduces memory overhead under high load
3. Link-Time Optimization (~15% improvement)
- Thin LTO for release builds
- Fat LTO for maximum performance (
--profile maxperf) - Cross-crate inlining and dead code elimination
[profile.release]
lto = "thin"
opt-level = 3
4. Parallel Block Building (8-16x more iterations)
- Up to 16 concurrent payload builders
- Each tries different transaction orderings
- Best payload selected at deadline
DefaultPayloadBuilderValues::default()
.with_max_payload_tasks(16)
.with_interval(Duration::from_millis(100))
.with_deadline(4)
Configuration: bin/tempo/src/defaults.rs:21-28
Combined result: Sustained >1000 TPS for payment transactions with sub-second finality.
Getting Started
Run a Node
# Install from source
git clone https://github.com/tempoxyz/tempo
cd tempo
cargo build --release --features "asm-keccak,jemalloc"
# Start node
./target/release/tempo node \
--chain andantino \
--http \
--http.addr 0.0.0.0 \
--http.port 8545
Build an Application
// Install SDK
npm install tempo.ts
// Setup client with Tempo extensions
import { createClient, http, walletActions } from 'viem'
import { tempo, tempoActions } from 'tempo.ts/chains'
import { parseEther } from 'viem'
import { privateKeyToAccount } from 'viem/accounts'
const client = createClient({
account: privateKeyToAccount('0x...'),
chain: tempo({ feeToken: '0x20c0000000000000000000000000000000000001' }),
transport: http(),
})
.extend(walletActions)
.extend(tempoActions())
// Send a batched Tempo transaction
const hash = await client.sendTransaction({
calls: [
{
to: tokenAddress,
value: 0n,
data: approveCalldata
},
{
to: recipientAddress,
value: parseEther("1.0"),
data: "0x"
}
],
nonceKey: 1n, // Parallel transaction sequence
feeToken: '0x20c0000000000000000000000000000000000001', // Pay gas in AlphaUSD
})
console.log('Transaction hash:', hash)
For React applications using Wagmi:
import { Hooks } from 'tempo.ts/wagmi'
import { parseUnits } from 'viem'
function SendPayment() {
const sendPayment = Hooks.token.useTransferSync()
const handleSend = () => {
sendPayment.mutate({
amount: parseUnits('100', 6),
to: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEbb',
token: '0x20c0000000000000000000000000000000000001',
})
}
return (
<button onClick={handleSend} disabled={sendPayment.isPending}>
Send Payment
</button>
)
}
Deploy a Token
// Using Wagmi hooks (React)
import { Hooks } from 'tempo.ts/wagmi'
function CreateStablecoin() {
const create = Hooks.token.useCreateSync()
const handleCreate = () => {
create.mutate({
name: "My Stablecoin",
symbol: "MYUSD",
currency: 'USD',
})
}
return (
<button onClick={handleCreate} disabled={create.isPending}>
Create Stablecoin
</button>
)
}
// Using Viem actions directly
import { Actions } from 'tempo.ts/viem'
import { client } from './viem.config'
const { token, receipt } = await Actions.token.createSync(client, {
name: "My Stablecoin",
symbol: "MYUSD",
currency: 'USD',
})
console.log('Token created at:', token)
Reference
Specification-Driven Development
Each precompile has two implementations:
- Solidity reference (
docs/specs/src/) - Source of truth - Rust production (
crates/precompiles/src/) - Optimized implementation
Foundry tests validate the Rust implementation against the Solidity spec:
// tempo-foundry integration tests Rust precompiles
// against Solidity reference implementations
#[test]
fn test_tip20_transfer_matches_spec() {
// Test Rust precompile behavior
let result = TIP20Token::transfer(sender, recipient, amount);
// Compare against Solidity reference
assert_eq!(result, solidity_reference_impl());
}
Codebase Structure
tempo/
├── bin/ # Binaries
│ ├── tempo/ # Main node (production binary)
│ ├── tempo-bench/ # Benchmarking and load testing
│ └── tempo-sidecar/ # Metrics and monitoring
│
├── crates/ # 30+ modular crates
│ ├── precompiles/ # Native payment features (Rust)
│ ├── primitives/ # Core types and transactions
│ ├── consensus/ # Consensus validation logic
│ ├── commonware-node/ # Simplex consensus integration
│ ├── payload/builder/ # Parallel block construction
│ ├── transaction-pool/ # Custom pool with 2D nonces
│ ├── evm/ # EVM configuration
│ └── node/ # Node builder and RPC extensions
│
└── docs/ # Vocs documentation site
├── specs/ # Solidity reference implementations
└── pages/ # SDK guides and tutorials
Language breakdown:
- Rust 2024 edition (requires 1.88)
- 13,758 lines in Cargo.lock
- Solidity for reference specs
- TypeScript for documentation and SDKs
Chain Configuration
Chain parameters:
- Chain ID: 42429 (testnet)
- Target block time: 1 second
- Gas limit: Dynamic based on network load
- Shared gas limit: 1/4 of total (for payment lanes)
- General gas limit: 1/10 of remaining (for non-payments)
Transaction pool:
- 50,000 pending transactions
- 50,000 queued transactions
- 150,000 max account slots (for 2D nonces)
- 8 parallel validation tasks
Configuration: bin/tempo/src/defaults.rs:30-51
Consensus:
- Simplex with BLS12-381 threshold signatures
- ED25519 for P2P authentication
- Epoch-based validator reconfiguration
- DKG for threshold key generation
Source: crates/commonware-node/src/consensus/
Status & Links
Implemented features:
- TIP-20 tokens with payment lanes
- Multi-currency gas payments
- Tempo transactions (batching, fee sponsorship, scheduling)
- WebAuthn/passkey signatures
- Native DEX for stablecoin swaps
- Compliance policy registry
- Sub-second finality
- Full EVM compatibility
Upcoming features:
- Account keychain (multi-key management) - Post-Allegretto hardfork
- Enhanced reward distribution system
- Validator delegation and staking
- Cross-chain bridges to Ethereum L2s
Testnet (andantino-1) is live. Mainnet launch planned for Q1 2026.
Links:
- Documentation: https://tempo.xyz
- GitHub: https://github.com/tempoxyz/tempo
- License: MIT OR Apache-2.0
Canteen