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

Scalus for Scala Developers

Build Cardano smart contracts using the Scala you already know. Get your first validator running in 30 minutes with familiar tools like IntelliJ IDEA, ScalaTest, and SBT.

Why Scalus Works for Scala Developers

You already understand:

  • ✓ Scala 3 syntax and type system
  • ✓ Functional programming patterns
  • ✓ Case classes, pattern matching, and collections
  • ✓ Testing with ScalaTest/ScalaCheck

You’ll learn:

  • Cardano’s eUTxO model - How blockchain state works
  • Plutus validators - On-chain code that controls funds
  • Scalus constraints - Which Scala features compile to UPLC
  • Blockchain-specific patterns - Datums, redeemers, script context

Time Investment: ~2-3 hours to first working validator, ~1 day to proficiency


Your Learning Path

Step 1: Quick Start (30 minutes)

Goal: Get your first validator running and debugged in your IDE

Check Hello Cardano Contract

Write you First Smart Contract

🎯 Quick Win: You’ll have a working Cardano validator and debug it with IntelliJ IDEA’s debugger. Yes, real breakpoints on blockchain code!

What You Just Learned:

  • Validators are just Scala objects with an @Compile annotation
  • You can debug them before deploying to blockchain
  • The development experience feels like regular Scala development

Step 2: Understand Cardano Blockchain (1-2 hours)

Goal: Understand how Cardano’s eUTxO model and validators work

Blockchain Concepts (New to You)

Coming from Web2? Think of validators as smart locks on digital assets. They define rules for who can unlock/spend funds.

Essential Reading:

Scalus-Specific Concepts

🎯 Quick Win: Build a multi-signature wallet validator using pattern matching and Scala collections.

Important Constraint: Not all Scala features compile to Plutus Core (UPLC):

Supported: vals, defs, case classes, enums, pattern matching, lambdas, recursion, inlineNot Supported: var, try-catch (except throw), mutable collections, arbitrary type classes

Always check Supported Features!


Step 3: Development Lifecycle (2-3 hours)

Goal: Build tested, optimized validators ready for testnet/mainnet

Testing & Quality

Testing Example:

class MyValidatorTest extends AnyFunSuite with ScalusTest: test("validator accepts valid signature") { val context = makeSpendingScriptContext( datum = ownerPkh.toData, redeemer = signatureData, signatories = List(ownerPkh) ) val result = compile(MyValidator.spend).runScript(context) assert(result.isSuccess) // Familiar ScalaTest! }

Build & Deploy

  • Compiling Validators - Generate UPLC bytecode and contract blueprints
  • Evaluating Scripts (In progress) - Run validators locally, check execution costs
  • Builtin Functions - Cryptographic operations and blockchain primitives

Off-Chain Transaction Building

🎯 Quick Win: Deploy a fully tested validator to Cardano testnet and build a complete off-chain application to interact with it.


Step 4: Master Advanced Patterns

Goal: Master optimizations and advanced validator patterns

Optimisations

Design Patterns & Security

🎯 Quick Win: Optimize a validator to reduce execution units by 20-30% using inlining and macros.


Common Questions from Scala Devs

”What Scala features can I use?”

The Good News: Most functional Scala works!

Fully Supported:

  • val, def, case classes, enums
  • Lambdas and higher-order functions
  • Pattern matching on case classes/enums
  • Recursion and tail recursion
  • given parameters and using clauses
  • inline and compile-time macros
  • Extension methods

Not Supported:

  • var (mutable variables)
  • try-catch (but throw works)
  • Mutable collections
  • Complex type class derivation
  • Effects (IO, Future, etc.)

See the complete list: Supported Features

”Can I use my favorite Scala libraries?”

For on-chain code: No. Validators compile to UPLC and can only use scalus.* libraries.

For off-chain code: Yes! Use any JVM library for:

  • Building transactions
  • Testing validators
  • Backend services
  • Frontend integration

Think of it like Scala.js: different target platform = different available libraries.

”How does compilation work?”

Your Scala Code (@Compile annotation) Scalus Compiler Plugin SIR (Scalus Intermediate Representation) UPLC (Untyped Plutus Core) Plutus Script (runs on Cardano)

Two modes:

  1. JVM execution - For testing and debugging (fast, debuggable)
  2. UPLC compilation - For on-chain deployment (verifiable, immutable)

“What about performance?”

On-chain execution is metered:

  • Memory usage (bytes)
  • CPU steps (execution units)
  • Script size (affects fees)

Scalus provides:

  • Built-in cost estimation - See execution units before deploying
  • Optimization passes - Reduce script size and costs
  • Profiling tools - Identify expensive operations

See: Advanced Optimizations

”How does error handling work?”

On-chain: No try-catch, but you can throw:

def spend(datum: Data, redeemer: Data, ctx: ScriptContext): Unit = val owner = datum.to[PubKeyHash] // This throws if condition is false require(ctx.txInfo.signatories.contains(owner), "Not signed by owner") // Explicit throw also works if !validSignature then throw new Exception("Invalid signature")

Off-chain (testing): Full Scala error handling:

test("validator rejects invalid signature") { val result = compile(MyValidator.spend).runScript(context) assert(result.isFailure) // Check it failed assert(result.logs.contains("Invalid signature")) // Check error message }

Common Pitfalls & Solutions

Pitfall #1: Using Scala stdlib types on-chain

Problem:

@Compile object Bad extends Validator: def spend(...) = val data = scala.collection.immutable.List(1, 2, 3) // ❌ Wrong!

Solution:

@Compile object Good extends Validator: def spend(...) = val data = scalus.prelude.List(1, 2, 3) // ✅ Correct!

Use scalus.prelude.List, not scala.collection.List.

Pitfall #2: Forgetting @Compile annotation

Problem: Code runs in tests but doesn’t compile to UPLC.

Solution: Always annotate validators:

@Compile // ← Essential! object MyValidator extends Validator

Pitfall #3: Using unsupported Scala features

Problem: Code compiles in Scala but fails in Scalus plugin.

Solution: Check Supported Features before using advanced features. Stick to simple val, def, case classes, and pattern matching.


Essential Cardano Resources

Blockchain Fundamentals

Scalus-Specific


Get Help

Need assistance? Connect with the Scalus community:

Happy building! 🚀

Last updated on