---
# System prepended metadata

title: Yet Another Payments System

---

# Simple Private Payment L2

In this I propose a design for a simple payments L2 with private free* stablecoin sends (* in specific usage regimes). In very short summary: the design dumps the transaction data (user zkps, merkle state roots) into blobs then runs a native implementation smart contract of the private send protocol resolve validity in the challenge protocol before paying block submiters through earned interest. This design for an app specific rollup is actually fairly easy to generalize to any app which can be resolved in a smart contract with a predictable state access pattern. Given the current mainnet fees it is expected that transaction costs would be less than a cent. 

## Transaction Structure

Transactions use a system which is a dervative of the ecash protocol used by zcash, with appropriate changes for the setup. Shielding transactions are the equivalent of deposits, unshielding are withdraws, and internal private pool sends are z2z transactions. Since the protocol is a utxo protocol we separate our state into two trees, one append only merkle tree with hashed committed private notes and one with the nullifiers from spent notes as a sorted merkle tree with each leaf having the index of a nullifier. In zk you enforce private blinded signatures, presence of the spent utxo notes in a prior tree root, and publicize the nullifiers of the spent notes. This design is fairly simple and has had several variants over time, but the most important part for our purpose is just the common structure of the output data which is used to verify transaction validity: an input state root, a zkp (ideally groth16 for size reasons),  some public added notes, some public used nullifiers. From this and with the context of the state trees we can can validate any transaction. 

## Proposal and Challenge protocol

Proposers are required to register with a stake, the stake is calculated based on the max gas usage of the one round challenge, total value secured limit, and the intended finality window. The computation is simply that the cost to fill all blocks with transactions that the proposer's stake is less than the cost of a single challange must be lower than the TVL limit. IE for a five eth stake and a 3 hour window at a 30 million block limit where the challenge costs 1 million gas: is 30 * 5 * (10800/13) = 124615.38 so then the system is secure up to 124615 eth locked. 

The proposer gathers user transactions and orders them in a blob such that each input nullifier root, input state root, output state roots, zk proof, added state roots up to a limit, and used nullifiers up to a limit (there are some size optimizations possible). The proposer submits this in a blob transaction along side their address and a domain separator. Then the proposer calls a proposal function on the smart contract, recording the number of transactions, the leaf and nullifier state roots and other relevant data. The number of transactions recorded is naturally enforced by the challenge protocol as it is used as a limit to where the data is loaded in the blob. From this time anyone can challenge the 

To challenge, the challenger specifies the index of the transaction which is invalid, then we use version hash of the blob and kzg proofs to open the data from the transaction in the blob. Then we can either prove that the zk proof doesn't verify or we can verify incorrect use of the merkle trees. Since the note tree is append only, we are able to construct it from the prior transactions. To prove fraud we first validate a path to the root, then we do a multi update proof properly appending the claimed new notes to compute the correct new root, if it doesn't match the claimed new root we have proved fraud. Similarly we use the sorting of the nullifier tree to predict where the nullifiers should be and open their indexes, if we open them and they are marked used we have proved fraud, if we mark them used then recompute the root and it doesn't match the new root we have proved fraud.

The security of this protocol comes from its simple inductive structure, at each point we only have to open either the prior or current transaction data, which increases the blobdata usage but reduces the challenge rounds, reducing the complexity at the same time as it reduces the needed challenge window. Given the current blobdata pricing this tradeoff is unlikely to have a meaningful impact on the cost as we can still include several hundred transactions per blob.

## Submission Economics and User Deposits/Withdraws 

Users can self sequence both deposits and withdraws by either adding a provably properly formatted note to the tree or consuming a note and adding a nullifier to the tree in zk. Not having sequencers submit deposits or withdraws means we don't have to do any forced transaction inclusion. Optionally, to prevent problems with sequencer block front running we can do a challenge protocol which adds nullifiers after block execution and requiring them to not be consumed in block, possibly with a one sequencing window delay for withdraws. (Note - since note tree is valid in a proof for any prior note tree, appending to it via deposits will not create ordering problems) This makes the deposits and withdraws more expensive for the user, but makes them cheaper for the sequencer which lowers net transaction costs for users (as l1 cost on block submission is expected to be the largest contributor to net cost).

There are a number of ways to do block scheduling and sequencer selection, from random weighted sampling of staked sequencers, to erc1559 gas like markets, or completely open sequencing. I prefer a model where user generated interest is directed to sequencer payments on a regular schedule with increased payments per number of submitted transactions. A simple way to do this is to allocate a payment of the prior user generated interest into windows, then in each window pay the sequencer with successful blocks equal to the percentage of transactions they submitted. In this first transaction block in a window the cost per transaction to sequencer is expected to approach 0 as otherwise more (spam) transactions will be submitted to consume to remaining cost. This negative cost block is how we can provide free (assuming mildly pro-social sequencers) or very low cost as even epsilon payments make it worth while to include. 

There is of course some problem with the optimal window size and transaction times and precommitments, as the interest might not support very fast sequencing. We could solve this with reserved submission slots via random weighted staker selection, but this adds implementation complexity. Given a stake weighted next sequencer selection protocol it easy to add strong (pre)confirmations by having the seqeuncer return a signed statement including the nullifiers of a transaction. The inclusion of a nullifier in the nullifier tree is easy to prove in the challenge window, and so would not add much complexity. For simplicity, however, it may be optimal to just do this out of protocol and without strong crypto economic 
guarantees.

There are two options to add user fees paid to sequencers: first we can add an incremental fee and have the user prove the fee in zk, secondly we can have the user pay fees in UXTO outputs to sequencer addresses. The downsides of public fees is that this will make user transaction more identifable, in particular the user transactions will be distugishable from ones the sequencer is submitting to fill blocks and receive more fees. In our system these spam transactions are actually desirable as long as they are statistically identical in public to those which are user generated because they increase the anonymity set.


## Conclusion

The rollup described here is actually relatively simple implement compared the current crop of general purpose of L2s, it uses or reuses public and well known cryptographic protocols, has a simple one round challenge game, and the smart contracts for sequencing are expected to be only around the complexity of a DeFi protocol. Despite this simplicity, the system still would be a stage 2 rollup with permissionless sequencing, relatively fast absolute finality, an easy path to very fast tx confirmations, and free to users private stablecoin sends. This feature set matches or exceeds the feature set of many of the new stablecoin payment L1s. 

This design pattern for app rollups is easily generalizable as each app rollup is just a native rollup with the native executor being a smart contract implementation of the protocol, leading to a simple 1 round challenge game. Given how underexplored app rollups are, there is also a very wide range of new ideas or patterns which can be employed when sequencing.

## Apendix A - Please do not arrest me

I am not a lawyer and one would need to be consulted for legally appropriate compliance protocols to be added to this system. This design is intended as an exercise in systems design for L2s, and is an illustration of how in the current stablecoin boom how we might prioritize not having transaction data visible to the public.

Finally, let me be clear that my intention with this design is for sequencers to be businesses who preform KYC/AML checks on their users so that we can use the power of total surveillance to bring hammer of justice down on any criminals or enemies of the American State.