skill·2026-03-22·8 min read

Aleo Program Deployment & Operations

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 transition or async transition entry points; when on-chain state updates are required, pair async transition ... -> Future with async 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, and leo upgrade interfaces
  • 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 pure transition logic 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 in build/.
  • Devnet: A local development network for testing deployments without spending real credits.

3. Project Setup

Create a New Project

bash
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

json
{
    "program": "my_project.aleo",
    "version": "0.1.0",
    "description": "My Aleo program",
    "license": "MIT",
    "dependencies": []
}

Environment Variables (.env)

bash
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

bash
leo fmt            # Auto-format source files
leo fmt --check    # Check formatting without modifying

Step 2: Build

bash
leo build

Outputs:

  • build/main.aleo — Compiled Aleo instructions
  • build/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)

bash
# Fast local execution for pure transitions — no proof generated
leo run <pure_transition_function> <inputs>

Step 4: Execute (With Proof)

bash
# Generate proof + transaction locally
leo execute mint "aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8s7pyjh9" 100u64

Step 5: Synthesize Keys Only

bash
# Generate proving/verifying keys without deploying
leo synthesize

JSON Output for Programmatic Use

All major commands support --json-output for structured results:

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

bash
# 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:

bash
# 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

bash
NETWORK=testnet
PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCBJ6gMzLuZhiVTLejxaYa8uDnB42FjBDRnAG
ENDPOINT=http://localhost:3030

6. Deployment

Deploy to Network

bash
# 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

bash
# 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

bash
# 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

bash
leo query program my_project.aleo
# Look for "edition" field in output

Perform Upgrade

bash
# 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

bash
# 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:

bash
# 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_KEY scoped 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 run for fast checks on pure transition functions; for async transition flows with finalize, validate with leo 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

ErrorCauseFix
"program already exists"Program ID is taken on the networkChoose a different program name
"insufficient base fee"Not enough credits for deploymentIncrease fee or reduce program size
"constructor failure"Constructor logic rejected the deployment/upgradeFix constructor logic or verify you meet the upgrade policy
"missing dependency"Imported program not found on networkDeploy the dependency first
"consensus version mismatch"Program uses features not yet activeCheck network consensus version and adjust
"invalid private key"Wrong key format or missing keyVerify PRIVATE_KEY in .env

11. Pre-Deployment Checklist

  1. leo fmt --check passes
  2. leo build succeeds with no warnings
  3. leo test passes all tests
  4. Sample inputs validated (leo run for pure transitions, leo execute for async/finalize flows)
  5. Constructor policy is appropriate for your use case
  6. Program name is unique on target network
  7. Dependencies are deployed (if any)
  8. Fee budget estimated (use leo synthesize to gauge program size)
  9. Private key is securely managed
  10. .env points 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

  1. Write program following aleo_smart_contracts skill
  2. Format: leo fmt
  3. Build: leo build
  4. Test: leo test
  5. Local run: use leo run <function_name> <inputs> for pure transition functions (no finalize)
  6. Start devnet: leo devnet --snarkos /path/to/snarkos
  7. Deploy to devnet: leo deploy --broadcast --devnet
  8. Execute on devnet: use leo execute <function_name> <inputs> --broadcast --devnet for all async/finalize functions
  9. Query state: leo query program <name> --mapping-value <map> <key>
  10. If upgrading: leo upgrade --broadcast --devnet
  11. When ready for testnet: Update .env endpoint, then leo deploy --broadcast

Sources