Skip to content

Instantly share code, notes, and snippets.

@folex

folex/reward.md Secret

Created April 3, 2024 23:34
Show Gist options
  • Save folex/1323bcf2dd12d002916316cad466d519 to your computer and use it in GitHub Desktop.
Save folex/1323bcf2dd12d002916316cad466d519 to your computer and use it in GitHub Desktop.
reward flow

The idea is rather simple, really.

Generate Temporary Wallets (metadata.json)

Generate a temporary ethereum wallet for every github account that gets rewarded, then encrypt each temporary wallet private key for all ssh pub keys that the user has in GitHub (eg https://github.com/folex.keys). We do encryption with the tool called age that allows to encrypt data for SSH pub keys, and decrypt with private SSH keys.

So, on a first step, we get a map of unencrypted ethereum wallets: alice => 0xaliceTmpWalletPrivateKey bob => 0xbobTmpWalletPrivateKey

Then, after encryption, we get map of encrypted ethereum wallets: alice => [0xabc, 0x123, 0x321] bob => [0xaaa, 0x333]

Here Alice has 3 ssh keys on github, and bob has 2 ssh keys on github.

Now, this map is saved as metadata.json. Anyone can download it, but only holder of Alice's SSH Private Keys can decrypt Alice's Temporary Ethereum Wallet.

Generate Merkle Tree of addresses of Temporary Wallets

Apart from metadata.json, we also generate Merkle Tree with addresses of all the Temporary Wallets. And put it on chain. This is to make it possible for Smart Contract to tell whether certain Wallet belongs to the set of Temporary Wallets or not.

Alice claims

Check if eligible

When Alice wants to claim, she first looks into metadata.json to see if it contains her GitHub handle. Then, she peeks each of the enrypted Temporary Ethereum Wallets, and tries to decrypt it with her SSH key of choice. So from [0xabc, 0x123, 0x321] she gets 0xaliceTmpWalletPrivateKey.

Chose which wallet to receive reward on

Now, Alice has to decide on which Ethereum Address she wants to receive the reward. Let it be 0xAliceMainWallet.

Generate proof

Alice then signs 0xAliceMainWallet address with 0xaliceTmpWalletPrivateKey, and builds a Merkle Proof for the address of the 0xaliceTmpWalletPrivateKey wallet. This information is enough to prove that:

  1. Alice has access to SSH key
  2. Alice has intention to send reward to 0xAliceMainWallet and nowhere else
  3. Wallet 0xaliceTmpWalletPrivateKey belongs to the Temporary Wallets set

This defines the proof format as: https://github.com/fluencelabs/dev-rewards/blob/main/proof-sh/proof.sh#L228

## userId, tmpEthAddr, signatureHex, merkleProofHex
echo "${USER_ID},${TMP_ETH_ADDR},${SIGNATURE_HEX},${MERKLE_PROOF}"

Where USER_ID is just an index in the metadata.json, which we use to check if this user has already claimed the tokens: https://github.com/fluencelabs/dao/blob/main/contracts/contracts/DevRewardDistributor.sol#L252

Send proof

Now, Alice will send the proof ${USER_ID},${TMP_ETH_ADDR},${SIGNATURE_HEX},${MERKLE_PROOF} to the Smart Contract. Either manually, or through the claim website

Proof verification in Smart Contract

  1. Check if this USER_ID has already claimed: https://github.com/fluencelabs/dao/blob/main/contracts/contracts/DevRewardDistributor.sol#L204
  2. Check if this TMP_ETH_ADDR belongs to the Temporary Wallets set https://github.com/fluencelabs/dao/blob/main/contracts/contracts/DevRewardDistributor.sol#L214
  3. Check if SIGNATURE_HEX is correct, and was made with intention to send money to msg.sender https://github.com/fluencelabs/dao/blob/main/contracts/contracts/DevRewardDistributor.sol#L216-L219

And that's it!

Useful links

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment