zkApp programmability is not yet available on the Mina Mainnet, but zkApps can now be deployed on Berkeley Testnet.
Security and zkApps
On this page, you will find guidance for how to think about security when building zkApps. We also provide a list of best practices and common pitfalls to help you avoid vulnerabilities.
Attack model
The first and most important step for zkApp developers is to understand the attack model of zkApps, which differs from traditional web apps in important ways. In essence, there are two new kinds of attack:
Adversarial environment: Like smart contracts in general, zkApps are called in an environment that you don't control. For example, you have to make sure that your zkApps is not misbehaving when passed particular method inputs, or when used as part of transactions different than you intended. The caller chooses how and with what inputs to call your zkApp, not you; and they might use this opportunity to exploit your application.
Underconstrained proofs: Successfully "calling" a zkApp really just means getting a proof accepted onchain which is valid against your zkApp's verification key. Such a proof could, for example, be created using a modified version of your zkApp code. This will work only if the modification doesn't change any of your constraints -- the logic that forms the proof. Hence, you have to take care that your zkApp code correctly proves everything it needs to prove; unproved logic can be changed at will by a malicious prover.
Note how the first point (adversarial environment) is relevant in all kinds of permissionless systems, like smart contracts. The second point, on the other hand, is specific to the zkApp model. In classical smart contracts, you can rely on the fact that the code you deploy is exactly the code that is executed; in offchain-executed zkApps, you can't.
While having your code modified due to underconstrained proofs may sound scary, we emphasize that most of the attack surface here is covered by o1js itself. It's o1js' job that when you call a.assertLessThan(b)
, you prove that a < b
under all circumstances; and the o1js team dedicates a lot of resources to the security of its standard library. The explicit goal is that when using o1js in an idiomatic way, you shouldn't have to worry about underconstrained logic.
That story changes when you start writing your own low-level provable methods. When doing so, you enter expert territory, and there are many new pitfalls to be aware of. We have dedicated a section to writing your own provable methods below.
If there is just one take away from this post, it should be to always keep an adversarial mindset. Be paranoid about your zkApp's security!
In the next section, we demonstrate the attack model of zkApps with a concrete example.
Example: TODO
TODO