Skip to main content

Choose a Smart Contract Language

You write a validator in a high-level language, and it compiles down to UPLC (Untyped Plutus Core), the one bytecode every Cardano node executes. Because the on-chain target is the same regardless of source language, choosing a language is mostly about ergonomics: which one lets your team write correct, efficient validators fastest.

This page helps you pick.

Everything compiles to UPLC

UPLC is a minimalist, lambda-calculus-based language: variables, functions, function application, constants, a fixed set of built-ins, and an error term. No loops, no mutable variables, no objects. That extreme simplicity is intentional: it makes on-chain execution deterministic and the node's evaluator small and auditable. The trade-off is that nobody writes UPLC by hand; you write something higher-level and let a compiler emit it. (If you want the low-level detail, see the UPLC reference.)

The practical consequence: your language choice does not change what's possible on-chain, only how pleasant it is to get there.

Aiken

Aiken is a language purpose-built for Cardano validators, with syntax borrowed from Rust, Elm, and Gleam. In the developer ecosystem survey it is the most-used language for writing validators, and it is the language the examples in this module are written in.

Why Aiken:

  • Lower barrier to entry: developers from Rust, TypeScript, or any ML-family language become productive quickly.
  • Fast iteration: the Rust-based compiler builds in seconds, not minutes.
  • Smaller scripts: optimized UPLC output means lower fees for your users.
  • Built-in testing: a test runner ships with the toolchain, so you write and run unit tests without extra tooling. (See Testing.)
  • Clean separation: Aiken is on-chain only. Off-chain code stays in whatever language your app uses (TypeScript, Python, Rust), which reinforces the on-chain/off-chain split Cardano's architecture wants.
  • Strong static typing: full algebraic data types, pattern matching, generics, and inference, modern type safety with no runtime or garbage collector.

Getting started with Aiken

Install Aiken with aikup, its official version manager:

npm install -g @aiken-lang/aikup # or: brew install aiken-lang/tap/aikup
aikup # installs the latest Aiken

See other install methods for Homebrew and the standalone script. Aiken ships a single toolchain: Language Server support across the major editors, a built-in test runner that reports CPU and memory costs (see Testing), and a compiler that emits a CIP-57 Plutus blueprint on every build.

To go deeper:

When to choose something else

Cardano's language diversity is a strength: because UPLC is a clean compilation target, many languages can target it (much as Rust, Go, and C++ all target WebAssembly). Pick by your team's existing expertise.

LanguageBest forNotes
AikenMost new projectsPurpose-built, fast, small output, built-in tests.
Plinth (Plutus Tx)Haskell teamsThe original language; full Haskell type system, on- and off-chain code sharing. Steeper learning curve and larger scripts.
PlutarchPerformance-critical validatorsFine-grained control close to writing UPLC by hand; the most verbose path, aimed at minimizing execution costs.
OpShinPython teamsWrite validators in a subset of valid Python; pairs with PyCardano.
ScalusJVM / Scala teamsScala 3 for both on-chain and off-chain; works with the JVM and JavaScript.
PebbleTypeScript-familiar teamsStrongly-typed, TypeScript-like syntax that compiles to UPLC.
MarloweFinancial contractsA domain-specific language, intentionally not Turing-complete, guaranteeing termination; has a visual playground.

A note on Plutus Tx (Plinth)

Plutus Tx was the original framework: you write Haskell, annotate it, and a GHC plugin translates it to Plutus Core and then UPLC. Its strengths are real: the full Haskell type system, shared types between on-chain and off-chain code, and a path toward formal verification. Its costs are equally real: a steep learning curve (Haskell + blockchain + Template Haskell), long build times, cryptic errors, and relatively large scripts. It remains important for projects deeply embedded in the Haskell ecosystem; for teams not already there, Aiken avoids those costs.

What you pay for: execution costs

On-chain execution is metered in ExUnits (Execution Units), across two dimensions:

  • CPU steps: the number of computational steps the script performs. Each built-in has a defined cost; integer addition is cheap, cryptographic hashing is expensive.
  • Memory units: the peak memory the script uses during evaluation.

Every script declares its budget up front, and there are per-transaction and per-block limits (protocol parameters that can change through governance). Two implications for your language choice:

  1. Feasibility: a validator that exceeds the per-transaction limit simply can't be used; you must optimize or restructure.
  2. Cost: higher ExUnits mean higher fees for your users, and a transaction that eats more of the per-block budget leaves room for fewer others.

This is the concrete reason "smaller, faster scripts" matters, and why Aiken's efficient output is a practical advantage. For tuning your own validator, see Optimization; to compare how different compilers' UPLC output actually performs on shared benchmarks, see UPLC-CAPE, an IntersectMBO framework that measures CPU units, memory units, and script size across compilers and publishes live reports.

Blueprints: the contract's interface

Whatever language you choose, the compiled output is described by a CIP-57 Plutus Blueprint: a machine-readable JSON document listing the validators, their datum/redeemer schemas, the type definitions, and the compiled code. Think of it as the ABI for a Cardano contract.

Blueprints are what let your off-chain code interact with a contract without reading its source: tools can generate TypeScript, Python, or Rust types directly from the blueprint, and different off-chain frameworks can all consume the same format. Aiken generates a blueprint automatically as part of its build. To turn one into type-safe off-chain code, see Write a validator › from validator to blueprint; to read one field by field yourself, see Reading a blueprint by hand.

Next steps

  • Lock and spend: write the off-chain transactions that interact with your validator
  • Testing: test Aiken validators with mock transactions
  • Contract library: real validators to read and learn from