ZK with No Added Trust Assumptions
This test is meant to prove how a VOID App can function with only a zkVM trust assumption. This is done by the VOID on-chain contract keeping track of a hash chain of all events input into the App. A zk proof is then generated that proves the state of the App for a given hash chain head. Put another way, the contract remembers what the inputs were and expects a proof against those specific inputs.
Test Explanation
The test scenario consists of two users interacting with the App. User1 first deposits some of TokenA (the native chain asset) and TokenB (a standard ERC-20 token) into the App. User2 then deposits some of only TokenA. User1 then adds liquidity to an AMM pool consisting of the two tokens.
The main body of the test consists of User2 using the AMM pool to swap TokenA for TokenB. After a couple of swaps, User2 then continues to withdraw a little bit of both TokenA and TokenB. User2 is able to finalize their withdrawal by submitting a proof to the EVM chain which then releases the tokens. The proof consists of a Merkle proof demonstrating the withdrawal occurred, along with a Groth16 proof that proves the state (that the Merkle proof is based on) is correct. This test uses the Risc Zero zkVM to do the state proving. This swap and withdrawal process is then repeated 10 times.
Finally, to cover all capabilities of the App, the final action is User1 removing all their liquidity.
Things to Note
- The cost of making a transaction for the VOID App is very cheap (around 35,000 gas no matter how complex the transaction)
- 3x cheaper than a typical on-chain swap (est. 110,000 gas)
- 4x cheaper than a typical on-chain NFT sale (est. 140,000 gas)
- The cost of withdrawing is on the more expensive side due to Groth16 proof verification (around 350,000 gas)
- However, this can be amortized if users/solvers are willing to wait for withdrawal finalization
- Even though proof generation has a latency to it, users can see the effects of their transaction with little latency querying directly from an App Node
Run the Test
1) Setup
Before running the test, make sure your machine is set up and ready to go. Refer to the Setup Guide for how to set everything up with dependencies, etc.
2) Start the EVM
The first thing to do is start a local EVM chain that will hold the VOID App contracts and where users will submit their transactions. Run the following script to start up a local EVM and deploy the contracts.
sh ./run-evm.sh
3) Start the Node
Next, we need to start the App Node. This Node will observe App transactions being submitted on the EVM chain and compute the resulting state of the App. Users use this node to get information about the state of the App in real-time. To start the Node, run the following script.
sh ./run-node.sh
4) Start the Prover
Next, we need a second Node that keeps track of state just like the first, but also generates zk proofs of the state. The reason this is a separate Node is because it runs a little bit behind on state while generating proofs. Users ping the Node for the latest App state, and ping the Proving Node when they want a proof of a previous state (for example, when trying to finalize a withdrawal on-chain). There are two options for running the Proving Node.
To start the Proving Node with GPU acceleration, run the script with the following option.
sh ./run-prover.sh cuda
Note: GPU proving takes a VERY long time to compile due to having to build the GPU kernels
To start the Proving Node with just CPU proving, run the script with the following option.
sh ./run-prover.sh
5) Run the Test
We now have everything we need to simulate users making transactions and interacting with the VOID App. Run the test with the following script.
sh ./e2e-test.sh