Intent Schema

Intent Schema

In SnarkSide, a trade intent is a cryptographically constrained data structure that expresses a trader's willingness to participate in a perpetual position under defined limits. The intent does not reveal any parameters publicly — rather, it exists as a zero-knowledge provable object that can be matched off-chain and settled on-chain only when verified by a constraint system.

The schema is designed for expressiveness, anonymity, and proof efficiency. Its construction leverages Poseidon hashing for SNARK-friendly commitments, nullifier logic for replay protection, and a salted structure to prevent correlation across time or attempts.

This page provides a full technical breakdown of the data fields within an intent, their cryptographic treatment, and how they are composed into provable commitment hashes.


Intent Fields

Each trade intent is composed of both public and private components — though in practice, all values are kept private during submission, and only their correctness is proven in zero-knowledge.

The key fields are as follows:

Field Name
Type
Description

side

uint8

0 = short, 1 = long

notional_size

uint256

Value of the position (blinded)

max_slippage

uint256

Tolerable price deviation (blinded)

leverage

uint8

Multiplicative leverage factor

expiry

uint64

Absolute block number after which the intent is invalid

salt

uint256

Randomized entropy for hash uniqueness

margin_commitment

PoseidonHash

Encrypted commitment to margin inputs

nullifier

PoseidonHash

Unique per-intent replay guard

intent_commitment

PoseidonHash

Final hash of the entire structure

The intent object is never stored on-chain in raw form. Instead, only the intent_commitment (along with a SNARK proof verifying its construction) is posted to the relayer network. On-chain, only the final match commitment — derived from two matching intents — is settled.


Poseidon Hashing in Intent Commitment

The Poseidon hash function is selected due to its performance in zkSNARK circuits — offering low constraint overhead and efficient recursive compatibility.

Each intent’s data is reduced to a single field element hash using the Poseidon sponge construction:

template IntentCommitment() {
    signal input side;
    signal input notional;
    signal input slippage;
    signal input leverage;
    signal input expiry;
    signal input salt;
    signal input margin_commitment;
    signal input nullifier;

    signal output commitment_out;

    component poseidon = Poseidon(8);
    poseidon.inputs[0] <== side;
    poseidon.inputs[1] <== notional;
    poseidon.inputs[2] <== slippage;
    poseidon.inputs[3] <== leverage;
    poseidon.inputs[4] <== expiry;
    poseidon.inputs[5] <== salt;
    poseidon.inputs[6] <== margin_commitment;
    poseidon.inputs[7] <== nullifier;

    commitment_out <== poseidon.output;
}

This commitment is the canonical identity of the intent. It is the only artifact retained post-proof. All downstream verification and matching operations reference this hash.

Because the salt is unique and random per intent, even identical trade parameters will generate different commitments — ensuring non-linkability.


Nullifier Logic

Nullifiers are critical to ensuring that each intent can only be matched once. They serve two primary functions:

  1. Replay Protection: Prevent reuse of an identical trade intent commitment by malicious relayers or duplicated submission.

  2. Match Finalization: Once an intent is used in a verified match, its nullifier is recorded in a global nullifier set on-chain. Future attempts to settle a trade containing the same nullifier will be rejected.

The nullifier is computed as:

nullifier = PoseidonHash(stealth_key, intent_salt)

This structure ensures that the nullifier is:

  • Unique to the user

  • Cryptographically unlinkable to wallet address

  • Validatable inside a circuit without revealing the user’s identity

The stealth_key may be derived from an ephemeral zkWallet keypair, and the salt is not reused across intents. The nullifier is included in the proof of a matched intent and verified on-chain before the vault root is updated.


Margin Commitment

Margin input is never posted as a raw value. Instead, users prove that they have committed sufficient collateral by constructing a margin_commitment, which itself is a Poseidon hash of:

margin_commitment = PoseidonHash(deposit_amount, token_id, stealth_recipient)

This allows the system to:

  • Validate margin availability during matching

  • Commit to a specific asset type without revealing it

  • Avoid preemptive liquidity tracking by adversaries

The margin commitment becomes part of the intent hash and must be re-proven at match time during vault integration.


Hash Composition and Integrity

All fields are structured and ordered before hashing. This ensures that malformed or ambiguous proofs cannot be constructed. For example, field ordering is rigidly enforced during intent creation to avoid commitment mismatch between user and verifier.

Each intent is paired with:

  • intent_hash: used for match proof constraint

  • proof.wtns: the witness file proving internal consistency

  • vk.json: verification key embedded into the relayer batch engine

Only intents with valid witnesses and fresh nullifiers are admitted into the matching pool. Upon settlement, the proof of match must include both intent hashes, which are re-verified against their own internal field commitments.


Summary

The SnarkSide intent schema is the foundation of the protocol’s privacy and correctness model. By using Poseidon hash commitments and zero-knowledge proofs to encode constraint-bound trade declarations, the system achieves:

  • Stateless off-chain coordination

  • Non-revealing participation

  • Replay-resistant matching

  • Verifiable proof-based execution

The result is an infrastructure that supports real perpetual markets under cryptographic constraints, without requiring exposure of trade metadata, user identity, or on-chain interaction at intent submission time.

Last updated