...
一、改进动机
Starcoin 在主网启动之时就在引入 Dao 以及链上治理,这一年里进行了十多次系统合约升级以及配置变更的投票治理,链上参与者也越来越多,运行稳定,无安全事故,但也发现了一些当前 Dao 系统的不足之处。
投票系统
当前的投票系统基于 Token 抵押模式,带来几个问题:
投票成本比较高。投票期间 Token 被锁定,尤其随着 DeFi 生态的发展,用户的投票机会成本会越来越高。这样的投票方式也很难并行发起几个投票提案。
没有 Token 的应用无法进行治理。如果尚未发布 Token 的应用或者社群,无法进行投票。
Dao 的标志与身份
当前的 Dao 系统假定一个 Token 代表一个 Dao,所有的 Token 持有者都是 Dao 的成员。Dao 对外没有一个账号地址标志,成员没有独立的身份标志,不利于社群类型的 Dao 发展,也很难适应有准入机制的 Dao。
工具与应用的支持
由于以上缺陷,当前的 Dao 只提供了一个投票界面,用于发起投票。没能提供一个用户友好的,创建和管理 Dao 的工具。
所以我们计划对当前的 Dao 进行改进升级,以解决以上不足。
二、改进目标
基于以上分析,我们设定以下改进目标:
基于快照的投票系统
将投票权重积累到一个具体的数值上,代表成员在这个 Dao 中的 reputation
每个成员有一个 IdentifierNFT 用于标识该用户的身份
Dao 可以适用于不同规模的 Dao,比如 Starcoin Dao,DeFi 项目 Dao,或者一个几人合作的独立工作室作为 Dao合作的独立工作室作为 Dao
三、基本概念
Dao
代表 Dao 实体,需要有一个类型标识来区分不同的 Dao,比如 Dao<X> 代表 X Dao。
Dao 账号
每个 Dao 对应一个链上账号,该账号拥有 Dao 实体,它的 signer 被托管到 Dao 合约中,所有交易都必须通过 Dao 来发起。
创建 Dao 的流程实际上是 Dao 发起者,先创建 Dao 账号,然后创建 Dao 实体,并将 Dao 实体写入 Dao 账号,同时将账号的 signer 托管给 Dao 的过程。
Dao 成员 NFT
Dao 创建的时候,会同时发行一个 NFT,复用 Dao 的类型标识,DaoMemberNFT<X>(名字待定)。该 NFT 创建之后就立刻存入 IdentiferNFT 容器中,和用户绑定。成员加入 Dao 的过程就是领取 DaoMemberNFT 的过程。
Dao SBT
Dao 创建的时候,会同时发行一个 Token,复用 Dao 的类型标识,Token<X>。这个 Token 并不自由流通,而是锁在 DaoMemberNFT 的 Body 中,代表用户在 Dao 中积累的 reputation。之所以不直接用一个数字来代表 reputation,主要是这样可以复用 Token 的一些基础工具,比如总量追踪,比如安全计算。
二、整体设计
文档参考: Move版 Snapshot 1.0需求列表
...
代码块 | ||
---|---|---|
| ||
// Dao.move module Dao { use DaoSpace; struct DaoSignerDelegate { cap: SignerCapability, // 托管的签名(这里一旦放进来,就没法再还回去了,且只有一份,没想好是放在space还是放在这里,暂时放这里) } struct DaoSpace { cap: SpaceCapability } struct DaoProposal { cap: ProposalCapability } struct DaoProposalSet { proposal_set: HashSet<u64, DaoProposal> } // 执行策略:转账 struct ExecutionTransferStrategy<phontem TokenT> { amount: u128, to: address, } // 项目方创建space public fun new_space( signer: &signer, voting_delay: u64, voting_period: u64, min_action_delay: u64) { //这里 Account 需要提供一个新的方法,允许用一个账号去创建另外一个 Delegate 账号。 let signer_cap = Account::create_delegate_account(); let dao_signer = Account::create_signer_with_cap(&siger_cap); //后面的操作切换到 dao_signer 身份进行操作 // 项目方托管 SignerCapability 到该合约 // 通过DaoSpace合约创建对应的结构 // 将DaoSpace权限存到当前合约 } // 参与投票方/创建投票方注册到space public fun register_to_space( signer: &signer, broker: address) { // 创建对应的NFT } // 参与投票方/创建投票方注册到space // 方便再上一层的DAO调用 public fun regiter_to_space_get_nft( signer: &signer, broker: address) : Option::Option<NFT<DaoSpace::NFTMeta, DaoSpace::NFTData>> { } // 根据 space_broker 来创建对应的proposal public fun create_proposal<ExecutionStrategy>( signer: &signer, // 创建者 space_broker: u64, // space 代理人 block_num: u64, // 快照高度 root_hash: vector<u8> // 快照根hash ); // 投票 public fun do_vote( signer: &signer, broker: address, id: u64, amount: u128, choice: u8, proof: &vector<u8>, side_nodes: &vector<u8>) { // 证明... // 取本地NFT // 用NFT投票 do_vote_with_nft(broker, id, choice, ); } // 用NFT来投票 // 方便上层DAO来调用 public fun do_vote_with_nft( broker: address, id: u64, choice: u8, nft: Option::Option<NFT<DaoSpace::NFTMeta, DaoSpace::NFTData>> ) { } } |
...
三、流程
参考:
...