Skip to main content

CommitRevealVault

The CommitRevealVault is the central contract in the Specter protocol. It accepts token deposits (commits) paired with cryptographic commitments and processes privacy-preserving withdrawals (reveals) validated by ZK-SNARK proofs.

Deployed address: 0x908aA11Dc9F2e2C3F69892acaDE112e831c0a14a

Constants

uint256 public constant BN254_SCALAR_FIELD =
21888242871839275222246405745257275088548364400416034343698204186575808495617;

The BN254 scalar field modulus. All commitments and nullifiers must be less than this value.

A 5-second cooldown is enforced between consecutive operations from the same address to mitigate front-running and replay attacks.

Functions

commit

function commit(
address token,
uint256 amount,
bytes32 commitment,
bytes32 quantumCommitment
) external

Deposits ERC-20 tokens into the vault and records a commitment.

Parameters:

NameTypeDescription
tokenaddressERC-20 token contract address. Must be authorized in AssetGuard.
amountuint256Number of tokens to deposit (in token's smallest unit).
commitmentbytes32Pedersen commitment hash = Poseidon2(secret, nullifier). Must be < BN254_SCALAR_FIELD.
quantumCommitmentbytes32Quantum-safe commitment (e.g., hash-based) for future post-quantum migration.

Behavior:

  1. Validates token is authorized via AssetGuard.isAuthorized(token).
  2. Transfers amount tokens from msg.sender to the vault via transferFrom (requires prior approval).
  3. Calls CommitmentTree.recordCommitment(commitment) to insert the leaf.
  4. Stores quantumCommitments[commitment] = quantumCommitment.
  5. Emits Committed.

Reverts if:

  • Token is not authorized.
  • Commitment is zero or >= BN254_SCALAR_FIELD.
  • Cooldown has not elapsed since the caller's last operation.
  • Token transfer fails.

commitNative

function commitNative(
bytes32 commitment,
bytes32 quantumCommitment
) external payable

Deposits native GHOST tokens into the vault. The deposited GHOST is burned via NativeAssetHandler.burnNative().

Parameters:

NameTypeDescription
commitmentbytes32Pedersen commitment hash. Must be < BN254_SCALAR_FIELD.
quantumCommitmentbytes32Quantum-safe commitment.

Behavior:

  1. Forwards msg.value to NativeAssetHandler.burnNative{value: msg.value}().
  2. Records the commitment in the CommitmentTree.
  3. Stores the quantum commitment.
  4. Emits Committed with token = address(0).

commitWithPolicy

function commitWithPolicy(
address token,
uint256 amount,
bytes32 commitment,
bytes32 quantumCommitment,
address policyId,
bytes32 policyParamsHash
) external

Deposits ERC-20 tokens with an attached reveal policy. The policy will be enforced during the reveal phase.

Parameters:

NameTypeDescription
tokenaddressERC-20 token contract address.
amountuint256Number of tokens to deposit.
commitmentbytes32Pedersen commitment hash.
quantumCommitmentbytes32Quantum-safe commitment.
policyIdaddressAddress of the policy contract implementing IRevealPolicy.
policyParamsHashbytes32keccak256 hash of the policy parameters that will be supplied at reveal time.

Behavior:

  1. Performs all checks and transfers from commit().
  2. Stores commitmentPolicies[commitment] = policyId.
  3. Stores commitmentPolicyParamsHashes[commitment] = policyParamsHash.
  4. Emits Committed.

commitNativeWithPolicy

function commitNativeWithPolicy(
bytes32 commitment,
bytes32 quantumCommitment,
address policyId,
bytes32 policyParamsHash
) external payable

Deposits native GHOST with an attached reveal policy. Combines the behavior of commitNative and commitWithPolicy.

Parameters:

NameTypeDescription
commitmentbytes32Pedersen commitment hash.
quantumCommitmentbytes32Quantum-safe commitment.
policyIdaddressPolicy contract address.
policyParamsHashbytes32Hash of policy parameters.

reveal

function reveal(
address token,
bytes calldata proof,
uint256[8] calldata publicInputs,
bytes32 commitment,
bytes calldata quantumProof,
bytes32 changeQuantumCommitment,
bytes calldata policyParams
) external

Withdraws funds from the vault by providing a valid ZK-SNARK proof.

Parameters:

NameTypeDescription
tokenaddressToken to withdraw (address(0) for native GHOST).
proofbytesGroth16 proof bytes (BN254 curve).
publicInputsuint256[8]Public inputs to the proof circuit: [root, nullifier, recipient, amount, tokenIdHash, policyId, policyParamsHash, changeCommitment].
commitmentbytes32The original commitment being spent.
quantumProofbytesQuantum-safe proof data (reserved for future use).
changeQuantumCommitmentbytes32Quantum commitment for any change output.
policyParamsbytesABI-encoded policy parameters; must hash to the stored policyParamsHash.

Behavior:

  1. Validates the Merkle root from publicInputs[0] via CommitmentTree.isKnownRoot().
  2. Extracts the nullifier from publicInputs[1] and checks/records it via NullifierRegistry.checkAndRecord().
  3. Verifies the ZK proof via GhostRedemptionVerifier.verifyProof(proof, publicInputs).
  4. If a policy is attached (commitmentPolicies[commitment] != address(0)):
    • Validates keccak256(policyParams) == commitmentPolicyParamsHashes[commitment].
    • Calls the policy via staticcall with a 100,000 gas cap.
  5. Transfers tokens to recipient (from publicInputs[2]):
    • For native GHOST: calls NativeAssetHandler.mintNativeTo(recipient, amount).
    • For ERC-20: transfers from vault balance.
  6. Emits Revealed.

Reverts if:

  • Root is not known.
  • Nullifier already spent.
  • Proof verification fails.
  • Policy validation fails.
  • Token transfer fails.

Events

Committed

event Committed(
bytes32 indexed commitment,
uint256 leafIndex,
uint256 amount,
address indexed token
);

Emitted when a deposit is recorded.

ParameterTypeDescription
commitmentbytes32The Pedersen commitment hash (indexed).
leafIndexuint256Position in the Merkle tree.
amountuint256Deposited amount.
tokenaddressToken address; address(0) for native GHOST (indexed).

Revealed

event Revealed(
bytes32 indexed nullifier,
address indexed recipient,
uint256 amount,
address indexed token
);

Emitted when a withdrawal is processed.

ParameterTypeDescription
nullifierbytes32The spent nullifier (indexed).
recipientaddressWithdrawal destination (indexed).
amountuint256Withdrawn amount.
tokenaddressToken address; address(0) for native GHOST (indexed).

Storage

commitmentPolicies

mapping(bytes32 => address) public commitmentPolicies;

Maps a commitment to its attached policy contract address. Returns address(0) if no policy is attached.

commitmentPolicyParamsHashes

mapping(bytes32 => bytes32) public commitmentPolicyParamsHashes;

Maps a commitment to the keccak256 hash of the policy parameters that must be provided at reveal time.

quantumCommitments

mapping(bytes32 => bytes32) public quantumCommitments;

Maps a commitment to its quantum-safe counterpart, stored for future post-quantum migration.

Usage Examples

Depositing ERC-20 Tokens

// 1. Approve the vault to spend tokens
IERC20(tokenAddress).approve(vaultAddress, amount);

// 2. Compute commitment off-chain: commitment = Poseidon2(secret, nullifier)
bytes32 commitment = 0x...; // computed off-chain
bytes32 quantumCommitment = 0x...; // quantum-safe hash

// 3. Commit
CommitRevealVault(vaultAddress).commit(
tokenAddress,
amount,
commitment,
quantumCommitment
);

Depositing Native GHOST

CommitRevealVault(vaultAddress).commitNative{value: 1 ether}(
commitment,
quantumCommitment
);

Depositing with a Timelock Policy

// Encode policy params and compute hash
bytes memory policyParams = abi.encode(lockUntil, expiresAt);
bytes32 paramsHash = keccak256(policyParams);

CommitRevealVault(vaultAddress).commitWithPolicy(
tokenAddress,
amount,
commitment,
quantumCommitment,
timelockExpiryAddress, // policy contract
paramsHash
);

Revealing (Withdrawing)

// Generate proof off-chain using the Specter SDK
// proof, publicInputs are produced by the prover

CommitRevealVault(vaultAddress).reveal(
tokenAddress,
proof,
publicInputs, // [root, nullifier, recipient, amount, tokenIdHash, policyId, paramsHash, changeCommitment]
commitment,
quantumProof,
changeQuantumCommitment,
policyParams
);