Skip to Content
Scalus Club is now open! Join us to get an early access to new features 🎉

Compiling Smart Contracts

Basic Compilation

Use PlutusV3.compile to transform your Scala validator into a Plutus script:

import scalus.compiler.Options import scalus.uplc.PlutusV3 // Compile your validator to Plutus V3 val compiled = PlutusV3.compile(MyValidator.validate) // Get the script for use in transactions val script = compiled.script val scriptHex = compiled.program.doubleCborHex

The compilation flow: PlutusV3.compile takes a validator entry point and produces a PlutusV3[A] object containing the script, its hash, and address.

Choosing a Plutus Version

Select the appropriate version for your use case:

import scalus.uplc.{PlutusV1, PlutusV2, PlutusV3} // Plutus V3 (recommended for new validators) val compiledV3 = PlutusV3.compile(MyValidator.validate) // Plutus V2 (for reference inputs, inline datums) val compiledV2 = PlutusV2.compile(MyValidator.validate) // Plutus V1 (legacy) val compiledV1 = PlutusV1.compile(MyValidator.validate)

Compilation Options

Control error traces and optimizations via Options:

import scalus.compiler.Options // Development: Include error traces for debugging given Options = Options.debug // Production: Minimal script size given Options = Options.release
  • Options.debug: Adds error location information (easier debugging, larger script)
  • Options.release: Minimal script size (for production)

You can also enable error traces on a compiled validator:

val compiled = PlutusV3.compile(MyValidator.validate) // Add error traces for debugging val withTraces = compiled.withErrorTraces

Complete Example

import scalus.* import scalus.uplc.builtin.Data import scalus.compiler.Options import scalus.cardano.onchain.plutus.v3.* import scalus.uplc.PlutusV3 @Compile object MyValidator { inline def validate(scData: Data): Unit = { val ctx = scData.to[ScriptContext] ctx.scriptInfo match case ScriptInfo.SpendingScript(_, datum) => require(ctx.txInfo.signatories.nonEmpty, "No signatories") case _ => fail("Must be spending") } } object MyContract { private given Options = Options.release lazy val compiled = PlutusV3.compile(MyValidator.validate) } // Get hex for use in transactions val scriptHex = MyContract.compiled.program.doubleCborHex

Encoding Options

UPLC programs can be encoded in several formats:

val program = compiled.program // Flat encoding (binary format) val flatEncoded = program.flatEncoded // CBOR encoding (wraps Flat) val cborEncoded = program.cborEncoded // Double CBOR encoding (standard for Cardano transactions) val doubleCborEncoded = program.doubleCborEncoded // Hex string of double CBOR (most commonly used in APIs) val hexString = program.doubleCborHex

What’s Next?

Once your validator compiles, you’re ready to publish and use it:

  • Blueprint Generation — Produce CIP-57 blueprints with the Scalus sbt plugin and verify script hashes
  • Deploying Contracts — Publish your compiled contract as a reference script UTxO on preview, preprod, or mainnet
  • Working with Contract — Set compilation options, generate CIP-57 blueprints, and get script addresses
  • First Contract Transaction — Lock funds at a script address and spend them with a redeemer
  • Building Transactions — Build and submit simple ADA transfers using TxBuilder
  • HTLC Tutorial — End-to-end example: contract, transactions, testing, and deployment
Last updated on