v0.17.0
Release Notes
Added
@UplcReprannotation system for fine-grained UPLC type representation control: opt types into
nativeUplcConstrrepresentation, propagate the annotation through lambda parameters/return
types, intrinsic return types,genSelectfield types, andIfThenElse/Applytarget-type
propagation; honored byFromData/ToDataderivation- native
UplcConstrintrinsics: equality (Eqdispatch viaequalsRepr),Optionoperations
(isDefined,isEmpty,get,getOrElse,map,flatMap,filter,exists,forall),
listappendedAll(eliminates per-element re-encoding when concatenating
@UplcRepr(UplcConstr)lists, used byQueuein the Knights benchmark) - Common Subexpression Elimination (CSE) UPLC optimizer pass — extracts repeated subterms into
shared lets with descriptive names (also extractsForce(Builtin)andForce(Force(Builtin))) - Common Context Extraction (CCE) UPLC optimizer pass — generalized to any single-hole position;
extracts shared lambdas with descriptive names Options.uplcOptimizersfor custom optimizer chain configuration- CEK machine profiler: per-source-location and per-builtin-function breakdowns plus a state
transition matrix;optimize-contractskill drives budget optimization workflow UtxoFlowframework for multi-transaction off-chain flows (Phase 1): branching, recursion/loop
support for local tail-recursive functions, parameterized flows
(DataParameterizedFlowCellValidator), compile-time checks for async closures and non-tail
recursionCellValidatorwith fullUtxoCelllifecycle:CellContext,TxBuilderintegration,
transitionSpend/transitionMinthelpers, hardened against V011/V005/V016/V024 vulnerability
patterns;AuctionCellreference example;Factorypattern for the Cardano UTxO modelscalus-blueprint-pluginv0.1 — sbt plugin for CIP-57 blueprint generation, withsbtn deploy
andsbtn blueprintcommands- Scalus plugin and example ejector (
#252) — eject contract examples into standalone projects
with cross-version sbt plugin support - recursive auction contract example with
Bindpattern handling fix - agent-based testing model in
scalus-testkit(ContractTestActor) - opaque-type support in
FromData/ToDataderivation and the compiler plugin; top-level opaque
types resolved via$packagemodule scanning;SIRModuleAnnotationmarker trait and
Module.annsfield - variadic factory intrinsics for
Map.singletonandMap.empty;List.unboxedNil[A]for
unboxed empty list creation Options.noWarnto silence SIR lowering warningsMiniBF-compatible Blockfrost API endpoints;UtxoSource.FromAssetinBlockfrostProvider- emulator preconfig support: pre-initialize from JSON files, allow custom datums, extended JS
API (tick,hasTx,getDelegation,getDatum,withState) assertEvalWithBudgetsandPlutusV3.withOptionsfor dual-budget testing across modes- optional Scalus on-chain identification tag marker (spec + implementation)
DynJsonutility for dot-syntax JSON navigation- gated CEK diagnostic assertions for representation/arity mismatches
(-Dscalus.assert.apply.data.to.uc=1):[APPLY-DATA-TO-NATIVE-UC],
[APPLY-VCONSTR-ARITY-MISMATCH],[CASE-VCONSTR-ARITY-MISMATCH],
[CASE-DATA-ARITY-MISMATCH] - documentation: Advanced Optimisations chapter, Authenticated Collections (Merkle Trees, MPF,
Bilinear Accumulators) split into static/incremental pages, Ledger Framework architecture,
TxBuilder close-out report, unit/property/TDD testing pages, thorough Lottery and Auction
example READMEs, Profiling page
Changed
- BREAKING: removed deprecated APIs marked
@deprecatedsince 0.14.x (including bloxbean
CCL APIs); MiMa filters added for the removed surface SumDataList/SumDataPairListunified into parameterizedSumBuiltinList(elementRepr);
SumPairBuiltinListseparated for pair-element listsPairDataandArrayDataaliases removed in favor of parameterizedProdBuiltinPair(fstRepr, sndRepr)andProdBuiltinArray(elementRepr)carried throughout the loweringPairListintrinsic providers added;SumDataPairListhead representation fixed- forced builtins naming convention updated from
__builtin_Nameto__Name cachedTopLevelHelperscache keys discriminate by call-site env capture and resolvedTypeVar
bindings (captureFingerprint(tps)plustypeUnifyEnv.filledTypes), so two callers with the
same SIR shape but different repr environments get separate helperspendingTopLevelLetRecsscoped per compile unit (no cross-compile leakage); only letrec
bindings reachable from the lowering root are wrappedstableKeyincludes structural repr info to reduceSumReprProxyidentity leaks across
cachedTopLevelHelperslookupsProductCaseUplcConstrSirTypeGenerator.upcastOnedispatches oninput.representationrather
than relabeling unconditionally — closes the unsafe-Data-as-UC relabel surface that produced
4-arg native selectors against Data scrutineesgenConstrLoweredis the canonical Constr-dispatch API;precomputedValuesremoved and the
dispatch chain pushed down into generatorsTypeVarKindsimplified toTransparent/Fixed;nativeTypeVarRepresentationand
nativeListElementsflags removed (the@UplcReprmachinery keeps native representations
end-to-end, eliminating dual lowering paths and per-testif/elsebudget snapshots)typeProxyreplaced withtypeProxyReprfor explicit representation control- removed
MerklePatriciaForestryradix-2/64 variants, keeping only the MPF-16 implementation;
Fork.neighborHashreduced to a single slice+blake2b - non-derived
Eqinstances now produce a warning;Eq.keyPairEqdeprecated scalus-pluginpublished withCrossVersion.fullto allow per-Scala-version publishing
Fixed
ProdDataConstr/DataConstr.isCompatibleOn(_, TypeVarRepresentation(_))was unconditionally
permissive: any TypeVar kind matched. For@UplcRepr(UplcConstr)types whose default rep is
native Constr, a Data →TypeVarRepresentation(Unwrapped)"compat" returned true, producing a
pure relabel and leaving Data bytes labeled as Unwrapped. DownstreamgenSelectthen emitted a
4-arg native-UC selector against a 2-argData.Constrscrutinee, leaving a 2-arg residual
lambda and aMultiplyInteger Apply LamAbsruntime crash. Fix: discriminateTypeVarKind—
Transparent/Fixedstay compatible;Unwrappedonly when
lctx.typeGenerator(tp).defaultRepresentation(tp) == this- KnightsTest:475 heisenbug: output
TypeVarleak via wrongeqClassinheritance and
non-deterministic tie-break inchooseCommonRepresentation - intrinsic binding internal
TypeVars no longer leak across dispatches; rebound at unify time
rather than stripped on merge-back FixedTypeVarinUplcConstrfields falls back to default rep instead of leaking abstract
Data marker;FixedTypeVarno longer leaks intoProdBuiltinPair/SumUplcConstr
fieldReprs- representations propagate through
TypeVarandFreeUnificatorwidenings so structural
unification doesn't drop the caller's repr context optTargetTypepropagates throughIfThenElseto branches;lvApplypreserves@UplcRepr
param reprs; CSE guarded against partial-builtin helpers- lazy
Casebranch evaluation in JIT to match CEK semantics - CEK and JIT evaluation of Plutus benchmark use-case scripts
- recursive enum derivation: allow unfilled type proxies in
AppliedTypeargs - non-recursive let bindings scoping; opaque types with type alias returns filter the full inline
proxy chain - pair pattern variables added to scope in PV11
genMatchPairData - UTxO query errors propagate as
TxBuilderException.UtxoQueryException slotToTimeuses.toLongfor Scala.jsBigIntcompatibility- CI JVM heap capped at 7GB to prevent OOM on GitHub Actions runners
Documentation
- Documentation: https://scalus.org/docs
- Getting started: https://scalus.org/docs/get-started
Contributors
![]() @nau |
![]() @rssh |
![]() @sae3023 |
![]() @fernweh0 |



