Home

Awesome

risc0-on-eth

An example of how to use RISC Zero's zkVM to protect an Ethereum smart contract

[!CAUTION] This example is outdated. You should instead be looking at risc0-ethereum.

The EvenNumber contract wraps a uint256 and provides set() and get() functions. The contract guarantees that the wrapped number is always even.

To enforce this guarantee, the contract's set() function requires a ZK proof that the new value is even. The proof is generated by running even-guests/is-even from within the RISC Zero zkVM.

An example of how to tie everything together is given by the even-cli tool, which gives us a way to invoke the contract's set() function from the command line. This tool:

Example usage is given below.

Get the tools

You'll need foundry and risc0.

Clone the repo and fetch the dependencies

$ git clone https://github.com/intoverflow/risc0-on-eth.git
$ cd risc0-on-eth
$ git submodule update --init --recursive

Test with forge

$ forge test -vvvvv

Test with anvil

Start the anvil service

$ anvil -a 1

...

Available Accounts
==================

(0) "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" (10000.000000000000000000 ETH)

Private Keys
==================

(0) 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80

...

Listening on 127.0.0.1:8545

We now save our private key into an environment variable. This will allow us to deploy our contracts and submit transactions.

$ export ETH_WALLET_PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80

Build the guest and deploy to Bonsai

First we build the guest:

$ cargo risczero build --manifest-path even-guests/is-even/Cargo.toml

...

ELFs ready at:
ImageID: b5738a9099282bf37dc46cac14865b81dd9dd230467b6c50a78e668458b886b5 - "target/riscv-guest/riscv32im-risc0-zkvm-elf/docker/is_even/is-even"

Once the guest has been built, we can deploy it to Bonsai. This requires that BONSAI_API_URL and BONSAI_API_KEY are set:

$ cargo run --release -- \
    deploy \
    --guest-elf=target/riscv-guest/riscv32im-risc0-zkvm-elf/docker/is_even/is-even
b5738a9099282bf37dc46cac14865b81dd9dd230467b6c50a78e668458b886b5

On success, the tool outputs the guest's Image ID. We save this value to an environment variable. This will allow us to deploy our contracts.

$ export GUEST_IMAGE_ID=b5738a9099282bf37dc46cac14865b81dd9dd230467b6c50a78e668458b886b5

We can optionally test the guest deployment (and our environment variables) at this time:

$ cargo run --release -- \
    test-vector \
    --image-id=${GUEST_IMAGE_ID} \
    --number=12345678

This command given above fetches a Snark receipt from Bonsai and print its contents. The output can be used to create unit tests for the EvenNumber contract.

Deploy the contracts

This requires that GUEST_IMAGE_ID and ETH_WALLET_PRIVATE_KEY are set:

$ forge script --rpc-url http://localhost:8545 --broadcast script/Deploy.s.sol

...

== Logs ==
  Guest Image ID is
  0xb5738a9099282bf37dc46cac14865b81dd9dd230467b6c50a78e668458b886b5
  Deployed RiscZeroGroth16Verifier to 0x5FbDB2315678afecb367f032d93F642f64180aa3
  Deployed EvenNumber to 0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512

...

Interact with the contract

First, let's query the contract's state:

$ cast call --rpc-url http://localhost:8545 \
    0xe7f1725e7734ce288f8367e1bb143e90bb3f0512 \
    'get()(uint256)'
0

Now let's update its state. We can do this by submitting a transaction. This requires that BONSAI_API_URL, BONSAI_API_KEY, and ETH_WALLET_PRIVATE_KEY are set:

$ cargo run --release -- \
    send-tx \
    --image-id=${GUEST_IMAGE_ID} \
    --chain-id=31337 \
    --rpc-url=http://localhost:8545 \
    --contract=e7f1725E7734CE288F8367e1Bb143E90bb3F0512 \
    --number=12345678

Lastly, let's query the state one more time to see that the value has been updated:

$ cast call --rpc-url http://localhost:8545 \
    0xe7f1725e7734ce288f8367e1bb143e90bb3f0512 \
    'get()(uint256)'
12345678