Swap output note — For the sender, containing the tokens received from the swap
Change note — For the sender, containing leftover input token value
Fee change note — For the sender, containing leftover fee-asset value
On-Chain Execution
After proof verification, the contract:
Spends input note nullifiers and records the transaction nullifier
Builds the swap path from the public inputs
Approves the input token (if ERC-20) for the Uniswap router
Executes the swap using the appropriate Uniswap V2 function
Measures the actual output amount via balance delta (supports fee-on-transfer tokens)
Computes the output note commitment using the actual amount
Combines the circuit's half-ciphertext with the actual value to create the full 9-field ciphertext
Adds 3 note commitments to the Merkle tree
Pays the relayer fee
Half-Encrypted Output Notes
The swap output amount is determined by the on-chain swap execution and cannot be known at proof generation time. The solution uses half-encrypted output notes:
The circuit encrypts only the ownership fields (owner_hash, rk_trapdoor) as a 6-field ciphertext
The contract executes the Uniswap swap and measures the actual output via balance delta
The contract appends a plaintext of the actual swap output value, coin_id, and a zero value_trapdoor
The contract computes the output note commitment using the actual swap amount
The value_trapdoor is fixed to 0 for swap output notes — this is a reserved value that the circuit enforces for swap operations specifically.
Swap Output Note Commitment
The swap output note commitment is computed on-chain: