Prove ERC20 Balance of Verified Account Owner (R0 v1.0)

👷 Signing and Steeling

Let's experiment with the powers provided by the Steel library by taking the base ERC20 example and extending it with the base ECDSA example. The ERC20 example only proves that some address holds a balance, with the essential proof being "Some address holds over 1 token at some ERC20 contract at the most recent block" That isn't a particularly useful statement... in our case we want to know that the owner of some account has a balance.

🫡 Our Mission

Constrain the ERC20 example to assert that the prover also holds the key to the account we are checking the balance of, hence is the "owner". We do this by verifying a ECDSA signature for the EVM account in question.

NOTE: The address and contract are optionally hidden to the verifier, so we can know the prover has a balance, but not DOX them!

🚀 Let's GO!

  1. Watch this playlist to learn the basics of RISC Zero.

  2. Use rzup to setup your development environment based on the correct version of the RISC Zero Getting Started Docs for you.

    # Get rzup
    curl -L https://risczero.com/install | bash
    # Follow command instructions to use rzup
    # ... This will take a while first time!
    
  3. Generate a new repo from the template for this workshop source:

    # Clone direct, or your new repo fom this template:
    git clone https://github.com/<YOUR_GH_USER>/risc0-v1-chess 
    # **OR** Clone the template direct:
    git clone https://github.com/nuke-web3/signing-and-steeling
    cd signing-and-steeling
    cargo r -r
    # ... This will take a while first time!
    # If you get errors, see step one to get setup!
    
  4. Take a look at the structure of the code and key files:

    signing-and-steeling
    ├── README.md
    ├── Cargo.toml           # 📝 Config = MUST use consistent R0 versions!
    ├── methods
    │   └── guest
    │       └── src
    │           └── main.rs  # 🧰 Guest = Game Logic to be proven 🌟
    └── src
        └── main.rs          # 🏃 Host = Execution of guest & GUI & more unproven
    

    Other files may need some minor adjustments, but is essentially boilerplate for the context of this workshop.

  5. Extend the ERC20 balance check to ensure that the prover is the owner of the account being checked.

⚠️ SPOILERS ⚠️

One possible solution with comments and tips

📝 Key Takeaways

  • Use crates in the zkVM without modification - no need to rewrite in circuits or zkDSL!
  • Use standard patterns like println! & fmt! normally for basic experiments and debugging in DEV_MODE.
  • 10s on lines of code overall -> useful proof, easily extensible!
  • There is still many risks of creating privacy and security faults via bugs and all the normal ways cryptographic systems can break down...

🧠 You don't need to know the deeper cryptographic details to build proof systems using zkVMs... BUT don't forget you are building a cryptographic system!

With zkVMs you are NOT abstracting the requirement for robust design and audits of your proof system!

🤓 Taking it Further

Here are some ideas to keep extending this example to learn more:

  • Take the core logic and host workflows and embed them into a coprocessorwith the Foundry Template- NOTE: versions MUST match throughout for Cargo.toml with respect to risc0-... dependencies.
  • Fix the replay attack inherent in this example to ensure the prover is the key holder, rather than anyone that has a valid signed message for this proof.
  • Bench and optimize the guest program, as there are likely ways to make this example much more performant!