Aleo Program Deployment & Operations
1. Overview
This skill covers the complete lifecycle of deploying Leo programs to the Aleo network: project setup, building, local testing, devnet setup, deployment, execution, upgrades, fee management, and dependency resolution.
Version & Canonical Syntax
- Target: Leo compiler >= 3.5.0
- Canonical syntax: Use
transitionorasync transitionentry points; when on-chain state updates are required, pairasync transition ... -> Futurewithasync function finalize_NAME(...); include a constructor with exactly one policy annotation (@noupgrade,@admin,@checksum, or@custom) for deployable programs - CLI assumptions: Command examples use the modern
leo build,leo test,leo run,leo execute,leo deploy, andleo upgradeinterfaces - When docs conflict: Prefer
leo --help, current Leo release notes, and the examples in this skill
2. Key Concepts & Glossary
leo run: Executes a function LOCALLY without generating a proof. Use this for puretransitionlogic and argument checks only; it does not create a transaction or execute on-chain finalize state updates.leo execute: Executes a function locally AND generates a zero-knowledge proof + transaction object. Use for production validation.leo deploy: Compiles the program and broadcasts a deployment transaction to the network. Costs credits.leo upgrade: Upgrades a previously deployed program (if the constructor allows it). Broadcasts an upgrade transaction.- Program ID: A unique identifier for a deployed program (e.g.,
my_token.aleo). Once deployed, no other program can use the same name on that network. - Edition: A version counter for a deployed program. Starts at 0, increments with each upgrade.
- Microcredits: 1 credit = 1,000,000 microcredits. All fees are denominated in microcredits.
- Proving Key / Verifying Key: Generated during
leo build. The proving key is used to generate proofs; the verifying key is used to verify them. These are large binary files cached inbuild/. - Devnet: A local development network for testing deployments without spending real credits.
3. Project Setup
Create a New Project
leo new my_project
cd my_project
This creates:
my_project/
├── build/ # Compiled artifacts (generated)
├── src/
│ └── main.leo # Main program source
├── tests/ # Test files
├── .env # Environment variables
├── .gitignore
├── program.json # Project manifest
└── README.md
program.json format
{
"program": "my_project.aleo",
"version": "0.1.0",
"description": "My Aleo program",
"license": "MIT",
"dependencies": []
}
Environment Variables (.env)
NETWORK=testnet
PRIVATE_KEY=APrivateKey1...
ENDPOINT=https://api.explorer.provable.com/v2
SECURITY: Never commit .env files with real private keys to version control. Use placeholder values in examples. For production, use secrets managers or HSMs.
4. Build Pipeline
Step 1: Format
leo fmt # Auto-format source files
leo fmt --check # Check formatting without modifying
Step 2: Build
leo build
Outputs:
build/main.aleo— Compiled Aleo instructionsbuild/abi.json— ABI specification (input/output types for each function)- Proving and verifying keys for each function
Step 3: Local Run (No Proof, Pure Transitions)
# Fast local execution for pure transitions — no proof generated
leo run <pure_transition_function> <inputs>
Step 4: Execute (With Proof)
# Generate proof + transaction locally
leo execute mint "aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8s7pyjh9" 100u64
Step 5: Synthesize Keys Only
# Generate proving/verifying keys without deploying
leo synthesize
JSON Output for Programmatic Use
All major commands support --json-output for structured results:
leo build --json-output
leo run <pure_transition_function> <inputs> --json-output
leo execute mint "aleo1..." 100u64 --json-output
leo deploy --json-output
5. Devnet Setup
A local devnet lets you test deployment and execution without spending real credits.
# Start a local devnet (requires snarkOS installed)
leo devnet --snarkos /path/to/snarkos
# With options
leo devnet --snarkos /path/to/snarkos \
--consensus-heights 0 \
--clear-storage
Funded Development Accounts
Devnet comes with 4 pre-funded accounts. Use these in your .env:
# Account 0 (default)
PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCBJ6gMzLuZhiVTLejxaYa8uDnB42FjBDRnAG
# Account 1
PRIVATE_KEY=APrivateKey1zkp2RWGDcde3efb89rjhME1VYA8QMxcxep5DShNBR6n8Yjh
# Account 2
PRIVATE_KEY=APrivateKey1zkp2GUmKbVsuc1NSj28pa1WTQuZaK5f1DQJAT6vnPeTt8oy
# Account 3
PRIVATE_KEY=APrivateKey1zkpB9dvPAE6G7bxXvfBCfTfUwVhZSk4TFbdDyBFNxas6LVp
Configure .env for Devnet
NETWORK=testnet
PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCBJ6gMzLuZhiVTLejxaYa8uDnB42FjBDRnAG
ENDPOINT=http://localhost:3030
6. Deployment
Deploy to Network
# Deploy with default settings
leo deploy --broadcast
# Deploy to devnet
leo deploy --broadcast --devnet
# Deploy with priority fee
leo deploy --broadcast --priority-fees 1000000
# Deploy with private fee (using a record)
leo deploy --broadcast --fee-records <record_plaintext>
# Deploy with explicit private key (instead of .env)
leo deploy --broadcast --private-key APrivateKey1...
Deployment Cost Model
Deployment costs scale with compiled program size:
Total Cost = Storage Cost + Synthesis Cost + Constructor Cost + Namespace Cost
- Storage Cost: Proportional to the byte size of the compiled program
- Synthesis Cost: Proportional to the number of constraints in each function
- Constructor Cost: Cost of executing the constructor
- Namespace Cost: Depends on program name length:
- 10+ characters: ~1 credit
- 5-9 characters: ~10 credits
- 2-4 characters: ~1,000 credits
- 1 character: ~10,000,000,000 credits (effectively prohibitive)
TIP: Use longer program names to minimize namespace cost.
Verify Deployment
# Query the deployed program
leo query program my_project.aleo
# Check a specific mapping value
leo query program my_project.aleo --mapping-value account "aleo1..."
7. Execution on Network
# Execute a function on a deployed program (broadcasts transaction)
leo execute mint "aleo1..." 100u64 --broadcast
# Execute on devnet
leo execute mint "aleo1..." 100u64 --broadcast --devnet
# Check transaction status
leo query transaction <transaction_id>
Transaction Lifecycle
leo execute → Proof Generated → Transaction Broadcast → Pending →
→ Accepted (included in block) → finalize logic executed on-chain
OR
→ Rejected (invalid proof, insufficient fee, finalize failure)
8. Program Upgrades
Check Current Edition
leo query program my_project.aleo
# Look for "edition" field in output
Perform Upgrade
# Modify your src/main.leo, then:
leo upgrade --broadcast
What Can Change in an Upgrade
- Function logic can change
- New functions can be added
- New structs/records can be added
- New mappings/storage can be added
What Cannot Change
- Program name (program ID)
- Existing function signatures
- Existing struct definitions
- Existing record definitions
- Existing mapping names (values can still change)
- Constructor definition and its upgrade policy annotation cannot be modified or removed once deployed
9. Dependency Management
# Add a network dependency (deployed program)
leo add credits.aleo --network
# Add with specific network
leo add credits.aleo --network --network-name testnet
# Add a local dependency (sibling project)
leo add my_lib.aleo --local ../my_lib
# Remove a dependency
leo remove my_lib.aleo
Deployment Order for Multi-Program Projects
Dependencies must be deployed BEFORE programs that import them:
# 1. Deploy the library first
cd my_lib && leo deploy --broadcast
# 2. Then deploy the program that imports it
cd ../my_app && leo deploy --broadcast
Security Notes
- Store signing keys in environment variables or a secrets manager, never in source files
- Keep
PRIVATE_KEYscoped by environment so devnet and testnet credentials are never mixed - Use private fee records for sensitive operational flows where fee source privacy matters
- Validate imported dependency program IDs before deployment to avoid targeting malicious lookalikes
Performance Notes
- Use
leo runfor fast checks on puretransitionfunctions; forasync transitionflows with finalize, validate withleo execute - Reuse synthesized keys and build artifacts between local test cycles to reduce turnaround time
- Keep program names long enough to avoid extreme namespace fees for short names
- Batch state-verification queries after execution instead of polling every second
10. Common Deployment Errors and Fixes
| Error | Cause | Fix |
|---|---|---|
| "program already exists" | Program ID is taken on the network | Choose a different program name |
| "insufficient base fee" | Not enough credits for deployment | Increase fee or reduce program size |
| "constructor failure" | Constructor logic rejected the deployment/upgrade | Fix constructor logic or verify you meet the upgrade policy |
| "missing dependency" | Imported program not found on network | Deploy the dependency first |
| "consensus version mismatch" | Program uses features not yet active | Check network consensus version and adjust |
| "invalid private key" | Wrong key format or missing key | Verify PRIVATE_KEY in .env |
11. Pre-Deployment Checklist
leo fmt --checkpassesleo buildsucceeds with no warningsleo testpasses all tests- Sample inputs validated (
leo runfor pure transitions,leo executefor async/finalize flows) - Constructor policy is appropriate for your use case
- Program name is unique on target network
- Dependencies are deployed (if any)
- Fee budget estimated (use
leo synthesizeto gauge program size) - Private key is securely managed
.envpoints to correct network endpoint
- Write programs using
aleo_smart_contracts - Test programs using
aleo_testing - Integrate with frontend using
aleo_frontend - Integrate with backend using
aleo_backend - Complete recipes in
aleo_cookbook
13. Agent SOP: Deployment Workflow
- Write program following
aleo_smart_contractsskill - Format:
leo fmt - Build:
leo build - Test:
leo test - Local run: use
leo run <function_name> <inputs>for pure transition functions (no finalize) - Start devnet:
leo devnet --snarkos /path/to/snarkos - Deploy to devnet:
leo deploy --broadcast --devnet - Execute on devnet: use
leo execute <function_name> <inputs> --broadcast --devnetfor all async/finalize functions - Query state:
leo query program <name> --mapping-value <map> <key> - If upgrading:
leo upgrade --broadcast --devnet - When ready for testnet: Update
.envendpoint, thenleo deploy --broadcast