ERC721 Extension for zk-SNARKs

I feel like you can accomplish this with much lighter-weight technology.

Just use regular stealth addresses:

  • Every user has a private key p (and corresponding public key P = G * p)
  • To send to a recipient, first generate a new one-time secret key s (with corresponding public key S = G * s), and publish S
  • The sender and the recipient can both compute a shared secret Q = P * s = p * S. They can use this shared secret to generate a new address A = pubtoaddr(P + G * hash(Q)), and the recipient can compute the corresponding private key p + hash(Q). The sender can send their ERC20 to this address.
  • The recipient will scan all submitted S values, generate the corresponding address for each S value, and if they find an address containing an ERC721 token they will record the address and key so they can keep track of their ERC721s and send them quickly in the future.

The reason why you don’t need Merkle trees or ZK-SNARK-level privacy is that each ERC721 is unique, so there’s no possibility of creating an “anonymity set” for an ERC721. Rather, you just want to hide the link to the sender and recipient’s highly visible public identity (so, you can send an ERC721 to “vitalik.eth” and I can see it, but no one else can see that vitalik.eth received an ERC721; they will just see that someone received an ERC721).

You can generalize this scheme to smart contract wallets by having the smart contract wallet include a method:

generateStealthAddress(bytes32 key) returns (bytes publishableData, address newAddress)

which the sender would call locally. The sender would publish publishableData and use newAddress as the address to send the ERC721 to. The assumption is that the recipient would code generateStealthAddress in such a way that they can use publishableData and some secret that they personally possess in order to compute a private key that can access ERC721s at newAddress (newAddress may itself be a CREATE2-based smart contract wallet).

One remaining challenge is figuring out how to pay fees. The best I can come up with is, if you send someone an ERC721 also send along enough ETH to pay fees 5-50 times to send it further. If you get an ERC721 without enough ETH, then you can tornado some ETH in to keep the transfer chain going. That said, maybe there is a better generic solution that involves specialized searchers or block builders somehow.

14 Likes