Back
KASPA.NEWS Articles
Kaspa Core R&D Channel

Silverscript Makes Contract State Checks Safer

Wednesday, June 17, 2026

Silverscript PR #131 changes how the compiler handles output-state validation. The breaking part is narrow: validateOutputStateWithTemplate no longer accepts a fresh inline state object directly. Contract code must assign the new state to a typed struct value first, then pass that value into the validation call. (source) (Silverscript PR #131)

Silverscript source that still uses the old shortcut needs a small update when recompiled: move the next-state literal into a typed struct value, then validate that value. (Silverscript PR #131)

The old shortcut looked convenient because a contract could pass an object literal straight into validateOutputStateWithTemplate. The problem is that the compiler then had to infer the state layout from the object fields. That is fragile when contracts use nested structs, especially when two nested fields share the same leaf name. PR #131 moves the compiler toward typed layout instead of field-name guessing. (Silverscript PR #131)

The old style was:

Silverscript
1validateOutputStateWithTemplate(0, {x: x + 1, y: 0x3412}, prefix, suffix, templateHash);

The new style is:

Silverscript
1TargetState next = {x: x + 1, y: 0x3412};
2validateOutputStateWithTemplate(0, next, prefix, suffix, templateHash);

The practical trade-off is simple: the new code is a little more explicit, but the compiler gets the actual struct layout instead of trying to reconstruct it from a loose literal. That is why the change can reject old source patterns at compile time while still being the safer design. (Silverscript PR #131)

The technical change is a new lowering step for validateOutputState and validateOutputStateWithTemplate before the general struct-lowering pass. The compiler now lowers these validation calls into internal forms after flattening typed state or struct values into the field order the script actually needs. (Silverscript PR #131)

This also fixes an important nested-state case. A contract can have left.id and right.id inside different structs, and those paths now remain distinct instead of collapsing into the same final field name, id. PR #131 adds compiler tests for nested State values, nested literals, and templated output-state validation where different nested structs reuse the same field name. (Silverscript PR #131)

The compiler errors also become more precise. Cases that previously failed with a generic state-field error now surface as struct-field errors such as missing fields, duplicate fields, or unknown fields. That is less forgiving for bad source code, but easier for contract authors to diagnose. (Silverscript PR #131)

This connects to the work already covered in Silverscript State Decoding Gets A Leaner Metadata Path. That article covered PR #130: state-decoding metadata and compile-time markers for output-state validation. PR #131 covers the next compiler-side piece, changing the path that turns state-validation calls into script logic.

There is also a separate dependency hygiene note around the same work: Silverscript still had rusty-kaspa dependencies pinned to tn12, and Sutton said those should move to master or a proper release tag. That is not the breaking language change itself, but it matters for keeping Silverscript aligned with current Rusty Kaspa dependencies. (source)

The result is a small compile-time break with a clear purpose. Contract authors using the old shortcut may need to rewrite those calls, but the compiler now has a stronger basis for validating output state, especially when contract state becomes more structured and nested. (Silverscript PR #131)


All sources link to public messages in the Kaspa Core R&D (public) Telegram channel.

More Kaspa Articles