Intent Circuit Design

Intent Circuit Design

The intent circuit is the foundational ZK constraint system used in SnarkSide to enforce the internal validity of a trade intent without revealing any of its contents. It encodes strict bounds on position size, leverage, slippage, and expiry, ensures cryptographic uniqueness via nullifiers, and constructs a final commitment hash used throughout the rest of the protocol.

This circuit is written in Circom, chosen for its performance, modularity, and broad compatibility with Groth16 proof systems. This section presents a detailed breakdown of the circuit implementation, discusses the rationale for each constraint, and explains how boundary violations are detected and rejected during proof generation.


Circuit Purpose

The intent circuit allows a trader to prove:

  • That their intended trade parameters fall within protocol-defined bounds.

  • That their margin commitment was properly constructed.

  • That their nullifier is unique and correctly derived.

  • That all inputs were composed into a deterministic Poseidon-based commitment hash.

This is proven in zero-knowledge and results in a compact SNARK that can be validated either by the off-chain relayer mesh or by an on-chain verifier contract during match settlement.

The output of the circuit is a single commitment hash, which is the canonical representation of the intent.


Circom Implementation

The following is a simplified but functionally complete version of the intent circuit, compatible with Circom 2.x:

template IntentCircuit(
    MAX_NOTIONAL,     // uint256: upper bound for trade size
    MAX_LEVERAGE,     // uint8: upper bound for leverage
    MAX_SLIPPAGE,     // uint256: upper bound for slippage
    MAX_EXPIRY_BLOCK  // uint64: maximum expiry window
) {

    // Public output: final Poseidon commitment
    signal output intent_commitment;

    // Private inputs
    signal input side;               // 0 or 1
    signal input notional_size;      // uint256
    signal input leverage;           // uint8
    signal input slippage;           // uint256
    signal input expiry;             // uint64
    signal input salt;               // uint256
    signal input margin_commitment;  // field element
    signal input nullifier;          // field element

    // --- Constraints on inputs ---

    // Must be a valid direction
    side * (1 - side) === 0;

    // Notional size must be > 0 and <= MAX_NOTIONAL
    notional_size >= 1;
    notional_size <= MAX_NOTIONAL;

    // Leverage must be >= 1 and <= MAX_LEVERAGE
    leverage >= 1;
    leverage <= MAX_LEVERAGE;

    // Slippage must be >= 0 and <= MAX_SLIPPAGE
    slippage >= 0;
    slippage <= MAX_SLIPPAGE;

    // Expiry block must be > current block and <= MAX_EXPIRY_BLOCK
    // Note: actual expiry validation occurs during match time
    expiry >= 1;
    expiry <= MAX_EXPIRY_BLOCK;

    // --- Poseidon commitment ---

    // Combine all fields into a deterministic hash
    component hasher = Poseidon(8);
    hasher.inputs[0] <== side;
    hasher.inputs[1] <== notional_size;
    hasher.inputs[2] <== slippage;
    hasher.inputs[3] <== leverage;
    hasher.inputs[4] <== expiry;
    hasher.inputs[5] <== salt;
    hasher.inputs[6] <== margin_commitment;
    hasher.inputs[7] <== nullifier;

    intent_commitment <== hasher.output;
}

This template is parameterized so that protocol-level maximums (e.g. max leverage) can be encoded at compile-time, minimizing runtime cost and ensuring uniformity across verifier deployments.


Input Constraints and Boundary Handling

Each input to the intent circuit is individually bounded. These constraints are hardcoded into the circuit and cannot be bypassed by the user.

Direction

Only two values are accepted for side: 0 (short) or 1 (long). The constraint:

side * (1 - side) === 0

enforces that any non-0/1 value will fail the circuit.

Notional Size

While the system accepts any 256-bit input for notional_size, the circuit ensures that:

  • It must be strictly positive

  • It must not exceed a preset MAX_NOTIONAL (e.g. 10⁶ * 10⁶ base units)

This protects against undercollateralized trades, arithmetic overflows in downstream match evaluation, and denial-of-service by invalid proof attempts.

Slippage

Traders may optionally specify a slippage cap. The circuit ensures it falls within system bounds. A slippage of zero is valid and indicates that the user will only accept execution at or better than their implied price commitment.

Slippage caps are enforced during off-chain matching as hard constraints, not suggestions.

Leverage

The leverage input is similarly bounded to prevent economically unviable or edge-case positions. This avoids excessive debt exposure on small-margin trades and simplifies downstream liquidation logic. Values outside the allowed range will cause proof generation to fail.

Expiry

The expiry value is specified as a block number relative to the L2 chain’s current state (or mocked block height in local dev environments). The circuit enforces that the expiry:

  • Is positive

  • Does not exceed a compile-time MAX_EXPIRY_BLOCK

Expired intents are rejected by relayers without requiring proof regeneration.


Cryptographic Soundness

The use of Poseidon as the commitment function ensures:

  • Field compatibility with R1CS SNARKs

  • Collision resistance within the structured permutation

  • Constraint efficiency (Poseidon constraints per hash: ~170–220 depending on implementation)

Because all intent fields are included in the final commitment, the proof acts as a complete semantic envelope for the user’s trade request — without ever disclosing its contents.

Any alteration of a single field would result in a commitment mismatch and cause downstream proof failures during match verification.


Security Implications

The intent circuit plays a foundational role in SnarkSide’s safety model. A valid intent proof ensures:

  • No malformed orders enter the relayer system

  • Replay is impossible due to nullifier enforcement

  • Matching logic operates on known-good commitments

  • Settlement cannot be forged without constraint satisfaction

Additionally, since the circuit rejects overleverage, negative slippage, and invalid expiry ranges, economic denial-of-service through malformed proofs is cryptographically impossible.


Final Output

The intent_commitment emitted from the circuit becomes:

  • The canonical identifier for the intent

  • The input to the off-chain MPC matcher

  • A required part of the match circuit

  • The anchor for margin verification and vault insertion

The user need only submit the proof and the hash — nothing more is revealed, stored, or observable.

The intent circuit is not just a guardrail. It is the API contract between the trader and the protocol. It defines what participation means — and what must be proven to engage.

Its role is simple, but its enforcement is absolute.

Last updated