前言¶
前一段时间 Fluence 开启针对 Github 开发者的空投活动,对符合要求的开发者空投 5000 枚 FLT,最高价格近 8000 美元(2024.5.15 约 2400 美元)。特别的是,领取该空投需要用户在本地运行一段代码,将执行结果复制到官网才能领取,并且锁仓 2 个月。笔者非常好奇,这种领取方式是否存在安全风险,因此展开了代码分析。
疑问¶
这是一条领取的交易记录:🔗,我们的问题如下:
-
官方是怎么用智能合约 solidity 验证你是 github ssh key 的拥有者的?
-
怎么查询领取进度?
-
领取交易会不会泄露你的evm领取地址与github的关联?
-
合约中用到了哪些省 gas 的方案?
前置知识¶
领取逻辑¶
项目方事先获取到所有开发者的公钥并给他们分配一个 user_id 和 temp_eth_account,然后使用开发者的公钥对 temp_eth_account 的私钥加密成 data。将所有的 temp_eth_account (以及 user_id)组成一个 Merkle Tree,将 Merkle Tree Root 放在合约里。因此用户要提供验证
用户用自己的私钥解密 data 得到 temp_eth_account 的私钥(从而得到这个 temp_eth_account 的控制权,这个 temp_eth_account 的地址是所有人都知道的)和 user_id,然后得到对应 Merkle Proof。然后用 temp_eth_account 签名一条信息:把钱发给 receiverAddress。最后把 user_id,temp_eth_account,MerkleProof 都发到合约 claim 函数里。
合约会校验 temp_eth_account 是否是最初项目方分配的(其实就是用 Merkle Proof 来证明 github_address 是最初那个 List 里的一个,但是保存所有 github_address 太占空间,所以只保存了 Root)然后验证签名来证明用户有控制权,一旦证明有控制权就发空投。
前端¶
仓库:🔗
-
ask_user_info 就是让用户输入自己的 github 名字和 receiverAddress,判断 github 名是否在列表中
-
choose_ssh_key 是让用户选择自己的私钥地址(不会上网所以不用担心)
-
decrypt_temp_eth_account 通过私钥解密 data 得到 temp_eth_account 的控制权
-
get_merkle_proof 得到 Merkle Proof 和 user_id
-
用 temp_eth_account 来签名:把钱发给 receiverAddress
-
获得 user_id、temp_eth_address、sign、Merkle Proof。将这串输出复制到去执行合约的 claimToken 函数。
合约¶
-
Merkle.verify 验证 temp_eth_account 是否是项目方最先发放的
-
验证签名是否来自 temp_eth_account
-
发钱
相关问题¶
如何查询领取进度(甚至会随时间减半)¶
当前已领取:
总供应:
甚至代码里领取量随时间是一直减半的:
领取交易会不会泄露你的evm领取地址与github的关联?¶
不会泄露。所有人只能看到:
-
github 用户的公钥
-
被 github 用户公钥加密过的 temp_eth_address 的私钥,即 data
-
temp_eth_address
-
receiverAddress
上面 2 中的 data 无法通过 github 用户的公开信息(公钥)求出 temp_eth_address,因此没有办法建立temp_eth_address 和 github 的关联,从而无法建立 receiverAddress 和 github 的关联。
人家用到了哪些省gas的方案¶
合约中使用 bitmap 来存储用户是否领取的状态,以此来节省空间。