Smart contract wallets increasing have a 'social recovery' feature. This allows a user to nominate 'guardians' - close friends and family - who are given the permission to restore the user access to their wallet if they lose their private key.

The Ethereum addresses of these 'guardians' are however stored in plain text on chain. This is both a privacy concern and potentially a security vulnerability, particularly if/when significant parts of individual's financial activity moves on-chain. It should be private.

What it does

zkSocialRecovery is an original, proof of concept attempt to make these 'guardian' addresses private. We have implemented a basic version of a smart contract wallet and integrated zero-knowledege technology to allow these addresses to be stored and used privately on-chain.

zkSNARKS and ZkWallet.sol

Specifically, we store in the storage of our ZkWallet.sol the hashed, encrypted version of a 'guardian's address. When a candidate 'guardian' wishes to restore a user's access to their wallet, by calling ZkWallet.zkRecover() the candidate guardian supplies a zk proof. This is created using a groth16 zkSNARK via the toolkit Zokrates, attesting to the fact that they indeed know the pre-image to the stored hash and so are a legitimate guardian.

If the proof validates, the ZkWallet.zkRecover() is allowed to proceed and the user is restored. This hack ships an interface/UI to make this process easier.

How we built it

  • Zokrates for writing the circuit, generating the trusted setup, computing witnesses, constructing the proof
  • solidity, truffle, ganache for writing, unit testing and deploying the smart contracts
  • solUI for creating the interface with which to interact with the Zk Smart Contract wallet

Challenges we ran into

  • Correctly calculating the correct sha256 hash of a variable > 128 bits in Zokrates - does not appear to map onto any web3.js hashing function
  • JavaScript bindings for zokrates are deprecated/unstable
  • solUI does not currently support smart contract functions that take array or bytes types as arguments

Current limitations

This is just an attempt at a proof of concept and there are limitations to the hack:

  • works for one Guardian address
  • UI does not fully support the contract methods - specifically the zkRecover method due to current lack of array support
  • Other privacy related limitations (as discussed below in what's next)

What's next for zkSocialRecovery

Proof of concept

This is only an attempt at a proof of concept, to show that zkSocialRecovery is possible.

There are privacy related technical challenges other than storing and using an encrypted on-chain address, this hack does not in reality fully obscure a guardians address. One of the main ones of these is that ZkWallet.zkRecover() is currently called by guardian, so their address is available and visible as msg.sender. We'll use a relayer in the future to get around this.

With more time, we want to refactor the wallet to add more guardians.

We are very keen to take things forward and try integrate into smart contract wallet providers!

Built With

Share this project: