Verifier Contracts
Verifier Contracts
Solidity Verifier ABI and Calldata Specification
SnarkSide’s privacy-preserving execution flow relies on on-chain verifier contracts to authenticate zero-knowledge proofs submitted by traders, relayers, and liquidators. These verifier contracts are generated from Groth16 .zkey files and deployed per circuit domain—e.g., IntentVerifier.sol, VaultVerifier.sol, OracleVerifier.sol.
Each verifier is a stateless, deterministic contract that validates SNARKs using elliptic curve pairings over the BN254 curve (also known as alt_bn128) and returns a boolean value indicating proof validity. This section defines the verifier contract structure, ABI interface, calldata encoding scheme, and SnarkSide’s approach to safe, gas-efficient verification logic on Ethereum-compatible chains.
Contract Generation Process
All verifier contracts are generated via snarkjs:
snarkjs zkey export solidityverifier circuit_final.zkey Verifier.solThe output is a Solidity contract that exposes:
A
verifyProof(...)functionVerification key constants
Elliptic curve pairing check logic (
Pairing.sol)
SnarkSide wraps each generated verifier in a domain-specific interface for internal use.
Solidity Interface (Generic)
function verifyProof(
uint[2] memory a,
uint[2][2] memory b,
uint[2] memory c,
uint[] memory input
) public view returns (bool r);Inputs:
a,b,c: Elements of the zkSNARK proof (G1,G2,G1)input: Array of public inputs (field elements ∈ Fr)
Output:
r = trueif proof is valid with respect to hardcoded verification keyr = falseif invalid or input mismatch
Calldata Layout
Verifier calldata is manually constructed or handled by SnarkSide middleware. For Groth16 on BN254, a valid calldata structure includes:
a[0] // G1 x-coordinate
a[1] // G1 y-coordinate
b[0][0] // G2 x c0
b[0][1] // G2 x c1
b[1][0] // G2 y c0
b[1][1] // G2 y c1
c[0] // G1 x-coordinate
c[1] // G1 y-coordinate
input[0]...input[n] // Public inputs (Fr elements)Example (IntentVerifier):
IntentVerifier.verifyProof(
[a0, a1],
[[b00, b01], [b10, b11]],
[c0, c1],
[intentHash, vaultRoot, fundingRate, expiration, oracleCommitment]
);All field elements are 254-bit integers, encoded as 32-byte big-endian words for RPC compatibility.
Gas Benchmarks
SnarkSide circuits are optimized for:
Minimal public inputs (≤6)
Short proof size (~192 bytes)
Batching-friendly verification (upgradable)
IntentVerifier
5
~420,000
VaultVerifier
6
~480,000
OracleVerifier
3
~390,000
LiquidationVerifier
4
~450,000
All verifiers use precompiled pairing operations available in EVM (via opcode 0x08), which ensures constant-time on-chain performance.
Security Properties
Proofs are circuit-specific and cannot be reused cross-domain.
Verifier rejects any malformed calldata or mismatched public input.
Reentrancy is impossible (pure view functions).
Optional: logging of successful proof hashes for replay protection or attestation.
Internal Routing
SnarkSide’s contracts use a shared ZkVerifierRegistry that maps circuit type → verifier address. This allows flexible verifier upgrades (e.g., Groth16 → Halo2) and batching strategies.
mapping(bytes32 => address) public verifierOf;Summary
SnarkSide verifier contracts are compact, deterministic, and gas-optimized modules for validating Groth16 zero-knowledge proofs on-chain. Through careful structuring of calldata, constraint ordering, and public input minimization, these verifiers form the foundation of SnarkSide’s trustless privacy-preserving execution engine. As recursion and new proving systems mature, future versions will support dynamic proof aggregation and on-chain recursive composition, enabling even more advanced forms of intent confidentiality and transaction obfuscation.
Last updated

