proof-of-assets
allows you to prove ownership of a certain amount of ETH (or any other L1 currency with equivalent account proof structure, e.g. MATIC/AVAX), without divulging owned addresses or exact balances. To achieve this, it first needs a signed message from the claimed address to verify ownership of the private keys, and then verifies a Merkle-Patricia trie proof provided by an RPC endpoint against a public root. It finally verifies that the true balance of the account is equal to or exceeds a claimed balance. If all those conditions are met, it outputs a publicly verifiable RISC Zero STARK.
Before using this tool, ensure you have the following software and tools installed:
- Rust (with
rustup
) - Nightly Rust (automatically installed by cargo using the
rust-toolchain
file)
Create an input file (e.g. input.json
) file following the input.example.json
template, and populate the relevant fields. These are as follows:
provider
: Ethereum JSON-RPC provider HTTP addressuser_address
: address of the user whose asset ownership is being provensignature
: an ECDSA secp256k1 signature of the Keccak-hashed eth-formatted message, with v = {00, 01} and not {1b, 1c}message
: a non-formatted string corresponding to the aforementioned signatureblock_number
: the block number to prove assets against. "latest" will provide the latest blockexpected_balance
: the claimed owned balance. Needs to be smaller or equal to the actual balance
And for proving values of contract slots, add the following fields:
contract_address
: the address of the contractbalance_slot
: the slot of thebalances
mapping. The actual slot will bekeccak(abi.encode(address, uint256(balance_slot)))
Two proving modes are available, prove_eth
and prove_erc
. They are used in the following way:
prove_native
allows you to prove ownership of native assets on Ethereum-equivalent chains. For example, ownership of ETH on Ethereum mainnetprove_contract
allows you to prove ownership of contract-based assets on Ethereum-equivalent chains. For example, for an ERC-20 token, you would want to prove that the balance slot associated to your address holds a given value
The corresponding verifying modes are given by the following functions, with the JSON receipt passed as input:
verify_native
verifies a proof produced byprove_native
verify_contract
verifies a proof produced byprove_contract
To execute the zk-STARK proving algorithm, simply run the following command within the repo:
cargo run --release -- --input <INPUT_FILE (input/receipt.json)> --command <COMMAND>
The program outputs a receipt file in target/proofs/receipt.json
, which contains a seal (the STARK itself), and a journal which is made of the serialized public inputs: the account trie root, the block hash, the claimed balance, the message, and if applicable the contract address and corresponding balance slot.