Skip to content

abstract-crypto/batcher-vault

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

27 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Batcher Contract on Aztec

The BatcherVault contract allows users to obfuscate their swap amounts when they trade on AMMs. It leverages an additive homomorphic encryption scheme to encrypt and aggregate users' input amounts without revealing individual amounts. The encrypted total amount is decrypted by a relayer who executes a batched swap. Later, users can claim their share of the output amount calculated based on their pro-rata share of the input amount for each batch round.

This vault doesn't only help conceal the users' input amount but also hide the sender address and output amount throughout the deposit and claim processes. Token transfer in both deposits and claims is performed privately without revealing msg_sender. The only visible information is "when" each deposit is made, as each deposit execution invokes public methods internally.

Note that the current implementation only makes input amounts invisible from the entire world but the party who decrypts the encrypted deposit. Details and solutions to this problem are described below.

Technologies & Credits

  • noir-elgamal by Jat & Josh: A noir library for Exponential ElGamal Encryption on the Baby Jubjub curve. This is the core component of this project, which is used to handle homomorphic encryption, addition, and decryption of users' deposits.

  • babyjubjub-utils by Jat: Node package implementing utility functions for interacting with the Baby Jubjub curve and the noir-elgamal` Noir package. This package is used in our ts test to perform the baby-giant-step algorithm for the full decryption of the deposit amount.

  • aztec-patterns by DeFi Wonderland: Types such are ElgamalAffinePoints and AffinePoint found in add-homomorphic project that integrates noir-elgamal are also used in the batcher vault contract.

Limitations & Solutions

1. Amount Visibility to Relayer

The Relayer, also called a decryptor, who owns the decryption key effectively can know all the individual deposit amounts if they look at encrypted data at each deposit tx. Furthermore, they have constant incentives to sell the decryption key to the highest bidder who is willing to pay money to monitor users' input amounts.

To mitigate this risk, this batcher vault implements a stake-and-slash mechanism that could discourage relayers from selling their decryption key as well as encourage them to keep it secure.

A relayer needs to stake a bonding token to the contract at deployment. This stake is slashed and sent to the party who proves that he knows the decryption key. For instance, if an entity disguised as a bidder successfully obtains the key, he can take the relayer's stake and optionally take over the relayer's role.

Another approach that is more preferable but challenging is to implement a threshold decryption scheme like Penumbra's. It generates, splits, and distributes the decryption key to multiple parties through the DKG procedure, allowing for decryption without nobody knowing the entire key.

Theoretically, it seems quite feasible to implement such a scheme for this batcher vault by having a Penumbra-like threshold decryption logic in Noir with baby-jub-jub-based Frost as the key generation algorithm.

This could be our future improvement task and the primary reason why we decided to build this feature with the Elgamal homomorphic addition instead of a note-sharing scheme in which individual input amounts can also be hidden from the external world but the relayer.

2. The Upper Limit of Input Amount

This batcher vault supports up to u64 value for the plaintext (deposit amount) while the noir-elgamal lib only supports up to u40. This is made possible by splitting u64 input value via bit shift and encrypting two separate u32. This limit can be increased to u128 or more but this obviously entails more storage and execution cost and longer decryption time.

In deposit_to_batch method:

        // split amount_out into 2 limbs
        let lower = (amount_out as u64 & 0xFFFFFFFF) as u32; // lower
        let upper = (amount_out as u64 >> 32) as u32; // upper

        // encrypt lower
        let (c1_0, c2_0) = noir_elgamal::exp_elgamal_encrypt(
               relayer_he_pubkey.point,
               lower,
               rands[0]
        );

        // encrypt upper
       let (c1_1, c2_1) = noir_elgamal::exp_elgamal_encrypt(
               relayer_he_pubkey.point,
               upper,
               rands[1]
        );

Stored in storage as EncryptedSum struct:

     struct EncryptedSum {
         limb0: ElgamalAffinePoints, // lower
         limb1: ElgamalAffinePoints // upper
     }

3. Delay

To offer a meaningful degree of privacy, the relayer is expected to batch several swap requests instead of one or a few. Hence, users may need to wait for a few blocks until their swap is completed. This PoC only lets the relayer execute the batch only once a minute as interval in BatchRelayer struct is set to 86400.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published