版本比较

密钥

  • 该行被添加。
  • 该行被删除。
  • 格式已经改变。

...

当前的 Dao 系统假定一个 Token 代表一个 Dao,所有的 Token 持有者都是 Dao 的成员。Dao 对外没有一个账号地址标志,成员没有独立的身份标志,不利于社群类型的 Dao 发展,也很难适应有准入机制的 Dao。

工具与应用的支持

由于以上缺陷,当前的 由于以上不足,当前的 Dao 只提供了一个投票界面,用于发起投票。没能提供一个用户友好的,创建和管理 Dao 的工具。

...

  1. 基于快照的投票系统

  2. 将投票权重积累到一个具体的数值上,代表成员在这个 Dao 中的 reputation

  3. 每个成员有一个 IdentifierNFT 用于标识该用户的身份NFT 用于标识该用户的身份,该 NFT 使不可转让的

  4. Dao 可以适用于不同规模的 Dao,比如 Starcoin Dao,DeFi 项目 Dao,或者一个几人合作的独立工作室作为 Dao合作的独立工作室作为 Dao

三、基本概念

Dao

代表 Dao 实体,需要有一个类型标识来区分不同的 Dao,比如 实体。 是否需要有一个类型标识来区分不同的 Dao?,比如 Dao<X> 代表 X Dao。Dao 。如果考虑到同一个 Dao 账号下只能有一个 Dao resource,不存在路径冲突问题,暂时不用考虑。

Dao 账号

每个 Dao 对应一个链上账号,该账号拥有 Dao 实体,它的 signer 被托管到 Dao 合约中,所有交易都必须通过 Dao 来发起。

创建 Dao 的流程实际上是 Dao 发起者,先创建 Dao 账号,然后创建 Dao 实体,并将 Dao 实体写入 Dao 账号,同时将账号的 账号,同时将 Dao 账号的 signer 托管给 Dao 的过程。

Dao 成员 NFT

...

Dao 创建的时候,会同时发行一个 Token,复用 Dao 的类型标识,Token<X>。这个 Token 并不自由流通,而是锁在 DaoMemberNFT 的 Body 中,代表用户在 Dao 中积累的 reputation。之所以不直接用一个数字来代表 reputation,主要是这样可以复用 Token 的一些基础工具,比如总量追踪,比如安全计算。

...

四、整体设计

文档参考: Move版 Snapshot 1.0需求列表

...

代码块
languagerust
// DaoSpace.move
module DaoSpace {

  struct Space {
    voting_delay: u128, // The delay between when a proposal is created, and when the voting starts. A voting_delay of 0 means that as soon as the proposal is created, anyone can vote. A voting_delay of 3600 means that voting will start 3600 seconds after the proposal is created.
    voting_duration: u128, // The duration of the voting period, i.e. how long people will be able to vote for a proposal.
    meta_data: vector<u8>, // 空间元数据,编码后存储在链上(可考虑存在链下)
  }
  
  struct NFTMeta {
    user: address,
  }
  
  struct NFTBody {
     weight: u128
  }
  
  struct SpaceCapability {
  }

  // 创建 space,一个账号只能创建一个(是否只能一个账户创建一个,待讨论)
  public fun create(signer: &signer, voting_delay: u128, voting_duration: u128, meta_data: &vector<u8>): SpaceCapability;
  // 查询 space
  public fun query(broker: address) : (u128, u128, u128);
  // 非托管账号 register
  public fun register(signer: &signer, space_broker: address, cap: &SpaceCapability) : NFT<NFTMeta, NFTBody>;
  // 非托管账号 unregister
  public fun unregister(signer: &signer, nft: NFT<NFTMeta, NFTBody>);
  // NFT 添加权重
  public fun add_weight(signer: &signer, nft: &mut NFT<NFTMeta, NFTBody>, weight: u128);
  // NFT 减少权重
  public fun reduce_weight(signer: &signer, nft: &mut NFT<NFTMeta, NFTBody>, weight: u128);
}

proposal:提案,即一个提案代表一次投票过程,该部分跟原有的流程类似,但是去掉了TokenType,该合约只处理提案的相关处理过程,不做其他无关的事情。Dao:代表治理的相关流程,该合约中处理底层Space与Proposal的拼装,将一些权限托管到该合约中,考虑还可以往上拆分,即将执行策略部分拆分到上层合约中。

代码块
languagerust
// DaoProposalDao.move
module DaoProposalDao {
   struct ProposalCapability {
    proposal_id: u64,
  }

  struct Proposal<Action>use DaoSpace;

  struct DaoSignerDelegate {
    ... // 现有的一些结构
    proposal_idcap: u64SignerCapability,
    voting_system: u8, // 投票类型有单选投票、二次投票、排名投票、加权投票等投票类型托管的签名(这里一旦放进来,就没法再还回去了,且只有一份,没想好是放在space还是放在这里,暂时放这里)
  }
 voting_start_time: u64,
  struct  voting_end_time: u64,
Dao {
    voting_block_numdelay: u64u128, // 投票快照高度The delay between when  voting_block_root: vector<u8>, // 投票快照高度的root hash
    action: Option::Option<Action>, // 执行策略的结构参数
  }
  
  struct Vote {
    /// vote for the proposal under the `proposer`.
    proposer: address,
    /// proposal id.
    id: u64,
    choie: u8, // 同意,反对,拒绝
    weighta proposal is created, and when the voting starts. A voting_delay of 0 means that as soon as the proposal is created, anyone can vote. A voting_delay of 3600 means that voting will start 3600 seconds after the proposal is created.
    voting_duration: u128, // 投票权重The duration of }the voting  
  public fun create_proposal<Action>(...,
      space_broker: address, 
 period, i.e. how long people will be able to vote for a proposal.
    space_id: u64,
      root_hashname: &vector<u8>): ProposalCapability;
  
  public fun cast_vote(
      signer: &signer,
, //人类可识别的名称标识,是否需要?
     proposer_brokercreator: address,
      id: u64, 
      amount: u128,
      choice: u8,
      cap: &ProposalCapability
    );
    
  public fun extract_strategy<Action>(id: u64) : Action;
};

Dao:代表治理的相关流程,该合约中处理底层Space与Proposal的拼装,将一些权限托管到该合约中,考虑还可以往上拆分,即将执行策略部分拆分到上层合约中。

代码块
languagerust
// Dao.move
module Dao {
  use DaoSpace;

  struct DaoSignerDelegate {
    cap: SignerCapabilitymeta_data: vector<u8>, // 托管的签名(这里一旦放进来,就没法再还回去了,且只有一份,没想好是放在space还是放在这里,暂时放这里)
  }
  
  struct DaoSpace {
    空间元数据,编码后存储在链上(可考虑存在链下)
    cap: SpaceCapability
  }
  
  struct DaoProposal {
    cap: ProposalCapability
  }
    
  struct DaoProposalSet {
    proposal_set: HashSet<u64, DaoProposal>
  }
  
  // 执行策略:转账
  struct ExecutionTransferStrategy<phontem TokenT> {
    amount: u128,
    to: address,
  }
  
  // 创建 项目方创建spaceDao
  public fun new_spacedao(
     signercreator: &signer, 
     voting_delay: u64, 
     voting_period: u64, 
     min_action_delay: u64) {
     //这里 Account 需要提供一个新的方法,允许用一个账号去创建另外一个 Delegate 账号。
     let signer_cap = Account::create_delegate_account(&signer);
     let dao_signer = Account::create_signer_with_cap(&siger_cap);
     //后面的操作切换到下面面的操作切换到 dao_signer 身份进行操作
     let dao = Dao{..};
     move_to(&dao_signer, dao);
     // 项目方托管托管 Dao 账号的 SignerCapability 到该合约
     move_to(&dao_signer, DaoSignerDelegate{cap: signer_cap});
     //初始化 dao 的时候无法一次性完成,需要先把 cap 都存到 creator 账号下
     // 通过DaoSpace合约创建对应的结构然后按照 plugin 的方式逐步初始化
  }
  
  // 将DaoSpace权限存到当前合约 将一个账号直接升级为 Dao
  public fun upgrade_to_dao(sender:signer, ...) {
     //基本逻辑同上,省去了创建账号的流程
  }
     
  // 参与投票方/创建投票方注册到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>>
  ) {
    
  }
}

proposal:提案,即一个提案代表一次投票过程,该部分跟原有的流程类似,但是去掉了TokenType,该合约只处理提案的相关处理过程,不做其他无关的事情。

代码块
languagerust
// DaoProposal.move
module DaoProposal {

  struct ProposalCapability {
    proposal_id: u64,
  }

  struct Proposal<Action> {
    ... // 现有的一些结构
    proposal_id: u64,
    voting_system: u8, // 投票类型有单选投票、二次投票、排名投票、加权投票等投票类型
    voting_start_time: u64,
    voting_end_time: u64,
    voting_block_num: u64, // 投票快照高度
    voting_block_root: vector<u8>, // 投票快照高度的root hash
    action: Option::Option<Action>, // 执行策略的结构参数
  }
  
  struct Vote {
    /// vote for the proposal under the `proposer`.
    proposer: address,
    /// proposal id.
    id: u64,
    choie: u8, // 同意,反对,拒绝
    weight: u128, // 投票权重
  }
  
  public fun create_proposal<Action>(...,
      space_broker: address, 
      space_id: u64,
      root_hash: &vector<u8>): ProposalCapability;
  
  public fun cast_vote(
      signer: &signer,
      proposer_broker: address,
      id: u64, 
      amount: u128,
      choice: u8,
      cap: &ProposalCapability
    );
    
  public fun extract_strategy<Action>(id: u64) : Action;
};

三、流程

参考:

Snapshot 说明文档

Snapshot X 说明文档

...