MisterPlus

Posted on Feb 04, 2022Read on Mirror.xyz

Implementing Soulbound NFTs with BrightID

Preface

This article is inspired by Vitalik Buterin's article titled Soulbound and a forum post by Triplespeeder titled Implementing Soulbound NFTs with BrightID.

In this article, I’ll demonstrate a proof-of-concept of Soulbound NFTs powered by BrightID. It’s gonna be a long ride, so let’s take this step-by-step.

BrightID Who?

At its core, BrightID is a decentralized protocol that we may take advantage of to identify unique humans. I won’t go into details about how they may achieve this in a decentralized manner, check out their whitepaper if you’re interested. In short, users rely on connections between other users to secure their unique BrightID identity.

BrightID uses more than one method to verify their users, some more strict than others, and applications can choose their preferred method to suit their needs. We’ll be taking a look at the Meets method, where a user becomes verified once they are connected with a BrightID seed member, and will never lose this verification status after they get it.

There’s no point proving you are a unique human just for the sake of proving it, that’s where BrightID apps come into place. Any application may register as a BrightID app, so long as they provide a unique app context and assign each of their users with a unique context id. In the context of an ethereum dapp, the unique context id can be a wallet address.

Once a user gets their Meets status, they may start linking their BrightID to any of the registered BrightID apps. Upon a successful link, a BrightID node will sign the user's verification data in the next operating cycle. A BrightID node API endpoint can be used to retrieve said signed data.

Here’s an example of signed verification data.

{
  "data": {
    "unique": true,
    "app": "snapshot",
    "context": "snapshot",
    "contextIds": [
      "0x7a38760c295f1ea086005214a279fb1280010483"
    ],
    "sig": {
      "r": "07976c27ccdcf6860567b6ad4b7f79faf82e7d5f38b67d5aa6b5d70052736c1f",
      "s": "011a401f4a745d3c6a470c78f5baca5aee45edab4e21ceb081fc2892bc05ca66",
      "v": 28
    },
    "timestamp": 1643984473,
    "publicKey": "02d2e244cb1a3f0692127486bd00115717b59fcd5edac2f57dd1ca53fcebc71373"
  }
}

To Ethereum We Go

Since the fundamental restrictions of a soulbound NFT need to be written into the smart contract, we’ll need to submit the signed verification data on-chain. Remember the signed data we just got from a BrightID node? We can have a contract function to check the signature for us, as long as the signer matches a trusted BrightID node, we can mark that address as verified forever.

Pity to the Thieves

But that only solves part of the problem: Supposedly we’re creating a soulbound NFT as a membership token. Right now, only the verified addresses can mint a token. But they’re non-transferable. In the event of a compromised wallet, your precious token won’t get stolen by the thieves, but they’ll have to stay in there forever. You probably don’t want to use a compromised wallet everytime you sign in to your favorite web3 club, right? Don’t worry, BrightID got your back.

Even though wallets are fragile as flowers, BrightID on the other hand, is much harder to compromise and much easier to restore. Once a BrightID user is connected with at least three trusted individuals, they can mark their connections as recovery connections. In the event of them losing their BrightID (e.g. uninstalled the BrightID mobile app), they can contact those recovery connections to recover their BrightID. The only way to compromise a BrightID is to have at least three recovery connections all go rogue, which is very, very unlikely.

Since BrightID is really resilient against attacks or losses, we can assume a user should always have access to their BrightID. Even though their ethereum wallet is compromised, they can still connect a new wallet to the same BrightID. And after submitting this new verification data on-chain, the smart contract would know that such two addresses belong to the same BrightID, the same person.

The solution is simple then: Only allow token transfers between the same BrightID, and overwrite the usual approval mechanic used by regular ERC721 standards to allow any address to transfer a soulbound token, as long as the spender, the owner and the recipient are all associated with the same BrightID.

Postscript

There are a few details about BrightID that I abstracted since they have little to no link to the main subject of this article. For example, a BrightID node would only sign the verification data if a user is sponsored.

I did take some time to write a demo of the supposed ERC721Soulbound standard, check it out if you’re familiar with smart contracts. Do submit issues if you found any, I’d be more than happy to improve on this concept.