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
- First Scalus smart contract - Explore Hello Cardano validator
Write you First Smart Contract
- Write your first smart contract - Build a spending validator
- Debug in your IDE - Set breakpoints and inspect execution
🎯 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
@Compileannotation - 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:
- Understanding eUTxO Model - How Cardano manages state (15 min)
- The EUTxO-Model - Plutus Pioneer Program - Learning details (25 min)
- Validators in Depth - Spending, minting, rewarding, certifying validators (20 min)
Scalus-Specific Concepts
- Supported Scala Features - CRITICAL: Not all Scala works on-chain!
- Primitive Types -
BigInt,ByteString,Datainstead ofInt,Array[Byte], etc. - FromData Derivation - Automatic serialization for case classes
🎯 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, inline
❌ Not 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 Smart Contracts - Use ScalaCheck for property-based testing
- Custom Data Types - Define datums and redeemers with case classes
- Collections -
List,AssocMapfor on-chain data
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
- Transaction Builder - Build complete Cardano transactions in Scala
- Building Your First Transaction - Send ADA and native tokens
- Spending UTxOs - Spend from validator scripts with redeemers
- Minting & Burning Assets - Create and manage native tokens
- Staking & Rewards - Stake delegation and reward withdrawal
- Governance - DRep registration and voting delegation
🎯 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
- Advanced Optimizations - Reduce script size and execution costs
- Modules - Build reusable validator libraries
- Real-World Examples - Study production patterns
- Transaction Builder - Build complete off-chain applications
Design Patterns & Security
- Design Patterns - Proven patterns for efficient multi-input validators
- Plutus Vulnerabilities - Common security issues and mitigations
🎯 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
givenparameters andusingclausesinlineand compile-time macros- Extension methods
❌ Not Supported:
var(mutable variables)try-catch(butthrowworks)- 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:
- JVM execution - For testing and debugging (fast, debuggable)
- 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
”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 ValidatorPitfall #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
- Cardano eUTxO Model - How state works on Cardano
- Plutus Overview - Cardano’s smart contract platform
- Cardano Developer Portal - Official developer resources
Scalus-Specific
- Scalus Examples - Real validator code
- API Documentation - Complete API reference
- Language Guide - Scalus language features
Get Help
Need assistance? Connect with the Scalus community:
- Join Discord: Ask questions
- Join Scalus Club: Check new features & discuss
- Examples: Real-world validator code
Happy building! 🚀