Skip to main content

The Pattern

Why Compact arithmetic needs casts

When you add two Uint<128> values, the result is not a Uint<128> — it’s a wider type that can hold any possible sum:
Returning or storing that wider value where a Uint<128> is expected fails to compile:
This forces every arithmetic result to be either explicitly cast back (after an overflow check) or assigned to a wider variable. There is no silent wraparound, and there is no / or % operator in Compact.

Overflow Checks

Addition Overflow

Before adding, verify that a + b won’t exceed the maximum value, then cast the widened result back. Example: Increasing total supply during mint.

Subtraction Underflow

Subtraction’s result type is already narrow enough for the assertion to make it safe; no cast is needed when the inputs are the same width. Example: Deducting balances, burning tokens.

Multiplication Overflow

Because Compact has no division operator, multiplication overflow is checked by widening the result and asserting it fits:
The cast to Uint<128> is a widening (zero-cost) cast; the cast back to Uint<64> is a narrowing cast that the preceding assertion makes safe.
Compact integers max out at Uint<248>. A full Uint<128> * Uint<128> product needs Uint<256>, which Compact does not support. If you need to multiply two 128-bit values safely, either narrow the operands first or perform the multiplication in the witness and check the result on-chain.
Compact does not provide / or %. If your problem requires division or modulo, perform it off-chain in the witness and pass quotient and remainder as inputs, then assert(dividend == quotient * divisor + remainder) inside the circuit. This is the standard ZK pattern for division.

Type Bounds

Different Uint sizes have different maximum values:
  • Uint<8> max: 255
  • Uint<16> max: 65,535
  • Uint<32> max: 4,294,967,295
  • Uint<64> max: 18,446,744,073,709,551,615
  • Uint<128> max: 340,282,366,920,938,463,463,374,607,431,768,211,455
Always check against the appropriate maximum for your target type before casting back.
const placement: top-level const is not allowed in Compact. Declare constants inside the circuits that use them (as shown above), or define them as Field literals at module level only if the type permits.

What’s Next

Transfer

Apply overflow checks in transfers

Minting

Use overflow protection when creating tokens