一、概述

通过 delegation_pool.move,最终用户可以参与质押,但是质押池的所有者代表整个质押池进行投票。部分投票通过允许委托人参与链上治理并根据他们的质押金额比例对治理提案进行投票,从而提出对 Aptos 治理的变更。

二、动机

部分投票通过允许更多用户参与治理,从而增加了去中心化。治理是区块链网络的重要组成部分,因为对区块链参数、区块链核心代码和 Aptos 框架的任何更改都必须通过链上治理投票。

以前,参与治理的最低质押要求是 100 万 APT。通过实施部分投票,只有质押了至少10APT,委托人就可以参与链上治理投票。

三、基本原理

考虑因素:

定义:

  • token 所有者是将其 token 质押到委托池中的“质押人(stakers)”
  • 投票人或委托投票人是具有投票权的人

考虑因素:

  1. 委托人只能在委托池的锁定周期结束于治理投票周期之后投票(锁定周期不能重置)。
  2. 任何具有锁定质押的委托人都可以参与治理 a. 需要注意的是,当质押人将资金添加到活跃池中时,质押是被锁定的。即使此后该池(“A”)后来变得不活跃,质押仍将被锁定,直到锁定周期结束。 b. 但是,如果委托人将质押添加到不活跃的池中,并且节点/池从未加入验证器集,则质押将不会被锁定。
  3. 所有新的委托池在创建时都将具有部分投票功能
  4. 对于现有的委托池,任何用户都可以提交一次性操作来启用部分投票功能。
  5. 委托池的投票人将由委托池模块管理。token 所有者可以将其投票委托给另一个钱包地址(“委托投票人”)。
  6. 一旦使用,投票就无法更改。换句话说,在投票后,投票人不能更改其投票。
  7. 如果有未使用的投票,以及/或者 token 所有者添加了质押,以及/或者委托池获得了质押奖励,这每轮都会发生,投票者将能够以新的投票权(按新的质押金额比例)再次投票。
  8. token 所有者可以随时提交交易以更改其委托的投票人,但更改只会在下一个解锁周期生效
  9. token 所有者可以在一个周期内多次更改投票人,但最后一次决定将在下一个周期中实施
  10. 需要注意的是,这将进一步意味着 Staking_contract 现在将有两个变化 a. 可以多次投票 b. 可以在质押池内部将投票分为是、否,或者只是部分未使用

替代解决方案:

委托池的操作者或所有者将代表整个池进行投票。这并不理想,因为它可能会给单个个人带来潜在的大量投票权。

四、规范

为了支持部分治理投票,我们希望投票账户由委托池模块管理,而不是由委托池所有者选择的地址管理。

委托人可以通过调用委托池模块的函数来参与Aptos治理,然后该模块控制管理的投票账户来参与Aptos治理。

提议的更改

  1. 委托池的投票人应该是其质押池的资源账户。委托池已经拥有该资源账户的签名能力。无需创建额外的账户。
  2. 弃用 delegation_pool::set_delegated_voter。启用部分治理投票后,任何人都无法更改委托池的投票人。

1. aptos_governance.move

现在,一个投票者可以通过调用 aptos_governance::vote 函数来对提案进行投票。然而,这个函数假设一个质押池只能一次性使用其全部投票权进行投票。为了支持部分治理投票,aptos_governance 模块需要允许一个质押池使用其部分投票权多次投票,只要这些投票的总投票权不超过该质押池的投票权。

提议的更改

  1. 添加一个新函数,aptos_governance::partial_vote(voter: &signer, stake_pool: address, proposal_id: u64, voting_power: u64,should_pass: bool)。投票人可以通过调用此函数使用其部分投票权进行投票。
    • 对于 voting_power 没有最低要求。
    • VoteEvent 中的 num_votes 字段可能不是 stake_pool 的总投票权。这可能会对索引器产生一些影响。
    • 此函数应该可以通过 CLI 调用。
    • 可以多次调用此函数。每次调用时,必须保持 <此新投票的投票权> + <此质押池在此提案上使用的投票权> <= <当前此质押池的投票权>
  2. 添加一个结构体,VotingRecordsV2,以跟踪每个质押池在每个提案上的投票权使用情况。
    • 此结构体仅存储在 @aptos_framework 中。
    • 该结构包含一个表<RecordKey, u64>,其中 u64 是已使用的投票权。
  3. 如果一个质押池在部分治理投票启用之前已经对某个提案进行了投票,那么即使在部分治理投票启用之后,该质押池也不能再次对该提案进行投票。
    • 在部分治理投票启用之前,未追踪已使用的投票权。剩余的投票权未知,因此该质押池不能再次对该提案进行投票。
  4. 现有的 aptos_governance::vote 的行为将略有不同。
    • aptos_governance::vote 仍然使用此质押池的所有投票权进行投票。
    • 在启用部分治理投票之前,一个质押池只能在提案上使用其当时全部的投票权进行一次投票。即使质押池后来(通过增加质押或获得奖励)拥有了更多的投票权,质押池也不能使用新增的投票权进行投票。
    • 在启用部分治理投票之后,一个质押池可以使用 aptos_governance::voteaptos_governance::partial_vote 进行投票,无论质押池是否已经使用 aptos_governance::vote 进行过投票。唯一的例外是质押池在部分治理投票启用之前已经对该提案进行了投票。

2. delegation_pool.move

投票权

委托人在委托池中的投票权是其活跃(active) + 待处理活跃(pending_active) + 待处理非活跃(pending_inactive)。为了更好地控制权限,委托人可以将其投票权委托给投票人地址。

提议的更改

  1. 添加一个结构体,GovernanceRecords 用于跟踪委托池的治理状态。该结构体跟踪:
    • 每个委托人的委托投票人。
    • 每个投票人的总投票权。
    • 每个投票人在每个提案上已使用的投票权。
  2. 添加一个函数 delegation_pool::delegate_voting_power(delegator: &signer, pool_address: address, voter: address)
    • 委托人可以将其投票权委托给另一个地址。
    • 委托人可以随时更改其投票人,但更改不会立即生效,而是要等到下一个锁定周期。
    • 记录委托人更改其投票人的上次到期的锁定周期。因此我们可以始终知道其最新的投票人。
  3. 添加表来跟踪投票者在活跃份额和非活跃份额池中的份额。
    • 目标是通过避免遍历所有委托人来节省 Gas。
    • 投票者的份额始终等于其所有委托人的份额之和。
    • 投票者的总投票权等于其在活跃份额和非活跃份额池中的 token 数量。

投票

委托人应该能够使用自己的投票权进行投票。委托人一旦投票就不能更改他们的投票。

提议的更改

  1. 添加一个函数,delegation_pool::vote(voter: &signer, proposal_id: u64, voting_power: u64,should_pass: bool)
    • 投票人可以以其部分投票权对提案进行投票,以防投票人代表一组用户(例如 CEX/Liquid Staking Service)。
    • 此函数将检查此投票人的投票权,然后使用其投票人的签名调用 aptos_governance::partial_vote
    • 此函数应该能够通过 CLI 调用。
  2. 添加表来跟踪每个委托人的投票权使用情况。
    • 键是 <委托人,提案 ID>,值是 已使用的投票权
    • 此表存储在其质押池的资源账户中。
    • 此表将在启用委托池的部分治理投票时创建。
  3. 添加一个新事件,VoteEvent{proposal_id: u64, delegator: address, delegation_pool: address, num_votes: u64, should_pass: bool} 用于委托人的投票。
    • 当成功投票时,将发出此事件。

提案

委托人应该能够在单个委托池中的投票权超过最低提案门槛时提出提案。

提议的更改

  1. 添加一个新函数,delegation_pool::create_proposal(proposer: &signer, delegation_pool: address, execution_hash: vector<u8>, metadata_location: vector<u8>, metadata_hash: vector<u8>, is_multi_step_proposal: bool)
    • 委托池模块检查调用者的投票权。如果其投票权符合最低提案门槛,则将此调用转发到 aptos_governance::create_proposal_v2
    • 此函数应该能够通过 CLI 调用。
  2. 添加一个新事件,CreateProposalEvent{proposal_id: u64, delegator: address, delegation_pool: address, execution_hash: vector<u8>, proposal_metadata: SimpleMap<String, vector<u8>>} 用于委托人的提案。
    • 当成功创建提案时,将发出此事件。

锁定周期

Aptos 治理要求质押池只有在其锁定周期结束后才能对提案进行投票/提出提案。这给委托池带来了问题 - 委托池中的所有委托人共享相同的质押池,因此他们共享相同的锁定周期。 如果一个委托池的锁定周期在提案到期时间之前结束,那么此委托池中的所有委托人必须等待,直到下一个锁定周期开始才能对此提案进行投票/提出提案。

一个经过计算的风险是,如果委托人的锁定周期在提案到期时间之前结束,并且提案到期时间与其锁定周期在同一周期结束,则委托人将没有时间对提案进行投票。

Aptos治理要求,只有当其锁定周期结束时间在提案的过期时间之后时,质押池才能对提案进行投票/提出提案。这给委托池带来了问题 —— 所有委托池中的委托人都共享同一个质押池,因此他们共享相同的锁定周期。 如果一个委托池的锁定周期结束时间在提案的过期时间之前,那么这个委托池中的所有委托人都必须等待,直到下一个锁定周期开始才能对这个提案进行投票/提出提案。

经过计算后得出的一种可能的风险是,如果某些委托者遇到以下情况:

  1. 他们的锁定周期结束时间在提案的过期时间之前。

  2. 并且提案到期时间与他们的锁定期在同一时期结束。

建议的更改

无。将保留当前的实现方式 —— 没有人可以重置委托池的锁定周期。

新创建的委托池

所有新创建的委托池都应启用部分治理投票。

建议的更改

delegation_pool::initialize_delegation_pool 中更改默认的投票人。

现有的委托池

如果在启用部分治理投票之前创建了委托池,那么这个委托池可能有一个由委托池选择的投票者。应该有一种方法来为这种类型的委托池启用部分治理投票。

建议的更改

添加一个新函数,delegation_pool::enable_partial_governance_voting(stake_pool: address)

- 此函数将把 `stake_pool` 的投票人更改为其自己的资源账户。
    - 此函数无需权限。任何用户都可以调用此函数。
    - 此函数应该能够通过 CLI 调用。

五、参考实现

请参阅 https://github.com/aptos-labs/aptos-core/pull/8090

六、风险和缺点

委托人可能并不总是关注正在链上提出的新治理提案,或者可能不希望积极参与治理。因此,他们可以将其投票权委托给另一个钱包地址,例如委托池的运营者。

七、未来潜力

  1. 部分投票可以通过允许中心化交易所(CEX)或流动质押应用程序代表其用户参与链上治理,从而为质押者提供更多的灵活性。
  2. 目前,委托人一旦投票就不能更改他们的投票,但我们可能在未来支持更改投票。

八、建议的实施时间表

目标定于第二季度末

九、建议的部署时间表

除了在委托池和 aptos_governance 模块中进行单元测试外,我们还将添加端到端测试,并在 devnet 和 testnet 上部署更改进行扩展测试,然后在主网中提出发布提案。