Compact 0.14.0
Compact is Midnight's dedicated smart contract programming language, designed for building secure, efficient, and adaptable decentralized applications.
23 January 2025
Compact 0.14.0 release notes
Today we are releasing version 0.21.0 of the Compact compiler. This release updates the language version to 0.14.0, which contains a number of improvements over language version 0.13.x, and some breaking changes. This is a big update to the language, so read these release notes carefully to understand the changes.
The new release is available for you to try out. If you recompile your Compact code with the new compiler, you may need to update your code to accommodate the breaking changes.
Summary of Changes
Language Changes
- [Breaking change] Witness return values may need to be "disclosed."
- Square brackets construct TypeScript-compatible tuples.
- You can use TypeScript-compatible destructuring.
- [Breaking change] The
Void
type is removed. - [Breaking change] The syntax of
for
loops is aligned with TypeScript. - [Breaking change] The
Cell
ledger ADT is now implicit. - [Breaking change] Ledger ADT names are now part of the standard library.
- Exported circuits are allowed to have the same name as witnesses.
- Improved syntax error messages.
Language Changes
[Breaking Change] Witness Return Values May Need to Be "Disclosed"
In Compact 0.14.0, witness return values are considered private data. To prevent unintentional "leaks" of this data (e.g., writing it to the public ledger), the compiler now enforces explicit disclosure using the new disclose
syntax.
Example:
// Pre-0.14.0 version:
poster = public_key(local_secret_key(), instance as Field as Bytes<32>);
// Post-0.14.0 version with disclosure:
poster = disclose(public_key(local_secret_key(), instance as Field as Bytes<32>));
Why We Made This Change
To ensure contract developers are deliberate about revealing potentially private data.
How to Fix Your Code
Wrap witness return values with disclose
when intentionally revealing private data.
Square Brackets Construct TypeScript-Compatible Tuples
Square brackets now construct tuples instead of vectors. Tuples allow precise tracking of element types and are compatible with TypeScript.
Example:
// Tuple example:
const tuple = [1, 2, 3]; // Type: [Uint<0..0>, Uint<0..1>, Uint<0..2>]
// Tuple subtyping example:
const vector: Vector<3, Uint<8>> = tuple;
Vector types still exist; tuples with identical element types are equivalent to vectors.
You Can Use TypeScript-Compatible Destructuring
Destructuring is now supported for tuples, vectors, and structs in const bindings and circuit parameters, including arrow circuits.
Example:
const [x, y] = [1, 2];
circuit example([a, b]: [Uint<8>, Uint<8>]): Uint<8> {
return a + b;
}
Limitations:
- The
...
(spread) syntax is not yet supported. - Destructuring does not work for ledger field assignments.
[Breaking Change] The Void
Type Is Removed
The Void
type has been replaced with the empty tuple type []
. A circuit or witness that does not return a useful value should now return []
.
Example:
// Old syntax:
circuit foo(): Void {
return;
}
// New syntax:
circuit foo(): [] {
return [];
}
Why We Made This Change
Void
behaved in unintuitive ways and was replaced with a simpler and more consistent unit type.
How to Fix Your Code
Replace occurrences of Void
with []
.
[Breaking Change] The Syntax of for
Loops Is Aligned with TypeScript
The syntax for for
loops now matches TypeScript. Use for (const x of collection)
instead of the previous Compact-specific syntax.
Examples:
// Old syntax:
for x in v do {
// Loop body
}
// New syntax:
for (const x of v) {
// Loop body
}
Why We Made This Change
To reduce syntactic differences with TypeScript.
How to Fix Your Code
Update for
loops to use the new syntax.
[Breaking Change] The Cell
Ledger ADT Is Now Implicit
Ledger fields no longer explicitly declare Cell
. Instead, Compact treats them as cells implicitly.
Example:
// Old syntax:
ledger state: Cell<STATE>;
// New syntax:
ledger state: STATE;
Why We Made This Change
To simplify ledger field declarations.
How to Fix Your Code
Remove Cell
from ledger field declarations.
[Breaking Change] Ledger ADT Names Are Now Part of the Standard Library
Ledger ADT type names (e.g., Counter
, Set
) are no longer built-in identifiers. They are now part of the standard library and must be imported explicitly.
Example:
import CompactStandardLibrary;
const counter: Counter = CompactStandardLibrary.Counter();
Why We Made This Change
To allow more flexible naming and modularity.
How to Fix Your Code
Import the standard library if you use ledger ADTs.
Exported Circuits Are Allowed to Have the Same Name as Witnesses
Exported circuits can now share names with witnesses. The compiler will flag ambiguities as errors, but most valid use cases will work without modification.
Improved Syntax Error Messages
Syntax error messages now indicate both the expected syntax and the issue encountered, making it easier to understand and resolve errors.
TL;DR
🚀 Compact language 0.14.0 introduces breaking changes and improvements:
- Witness disclosure: Use
disclose
for witness return values when needed. - Tuples: Square brackets now create tuples, compatible with TypeScript.
- Destructuring: TypeScript-compatible destructuring for tuples, vectors, and structs.
Void
removed: Use the empty tuple type[]
instead.for
loops: Aligned with TypeScript syntax.- Ledger fields:
Cell
is now implicit. - Ledger ADTs: Part of the standard library.
- Error messages: More helpful syntax errors.
Make sure to update your code to take advantage of these changes!