Skip to main content

Staking

总览

Conflux引入权益质押机制的原因有两个:一、权益机制提供了一种对占用存储空间更好的收费方式(相比于“一次付费,永久占用”)。二、该机制还有助于定义分散治理中的投票权。

在顶层,Conflux实现了一个内置的Staking合约,以记录所有账户的权益信息。通过向该合约发送交易,用户(包括外部用户和智能合约)可以存入/提取资金,也被称为合约内的权益。

用户可以通过调用 deposit(uint amount) 来存入用于抵押的金额,随后 amount 数量的资金将从其 balance 移至 stakingBalance. 需要注意的是该函数不是 payable 的,用户只需要指定抵押的金额而无需将资金转入到内部合约中。

用户还可以通过调用 withdraw(uint amount) 来提取余额。调用者可以调用该函数从Conflux质押合约提取部分代币。抵押资金将会及时的转入用户余额中。所有提款的顺序将按照先到先服务的方式进行处理。

锁定与投票权

通过锁定质押余额,用户可获取投票权以进一步进行链上治理。通过调用 voteLock(uint amount, uint unlock_block_number) 函数,一个帐户可以做出如下承诺:“我的 stakingBalance 在未来 unlock_block_number 中将始终具有至少 amount 的资金”。单个账户可以做出多个承诺,比如说“今年我将至少持有10CFX,并且在明年至少持有5CFX。” **一旦做出承诺,无法取消!**但是该账户可通过锁定更多的金额覆盖原有的承诺。每当账户尝试提取 stakingBalance 时,内部合约会检查剩余余额是否与锁定承诺吻合。

在此处我们将通过几个样例介绍锁定余额的逻辑细节。假设Conflux在今年的剩余时间将产生 x 个区块,在明年的产生 y 个区块。由于Conflux网络每秒能生成两个区块,因此 y 近似等于 2 * 60 * 60 * 24 * 365 。而 x 取决于您何时阅读到该文章。

  1. 假设一个账户的 stakingBalance 中有10CFX,如果其调用 voteLock(100 * 10^18, x) ,说明账户尝试锁定 100CFX. 但由于其缺少足够的 stakingBalance,交易执行失败。
  2. 然而,如果该账户调用 voteLock(8 * 10^18, x) ,则交易会成功。
  3. 随后,如果该账户调用 voteLock(6 * 10^18, x+y),交易同样会成功。这意味着交易执行后 2CFX 在今年结束时解锁,而另外 6CFX 会被锁定直到明年结束。
  4. 如果账户再调用 voteLock(0, x),没有任何事情会发生。在交易执行过程中交易不会触发错误。内置合约会将此调用视为无意义的承诺:该帐户在步骤 2、3 做出的旧承诺有效的前提下,再次承诺在今年结束前至少锁定 0 CFX.
  5. 如果该账户调用 voteLock(9 * 10^18, x+y),则两个较老的承诺将会因为“锁定 9CFX 直到明年结束是一个更强的承诺”被覆盖。

锁定对利息无任何影响。当账户成功取出抵押余额时,利息会将照常计算。

在任何时间,每一个锁定的金额将根据其解锁时间被分配0到1的表决权。锁定期超过1年的部分将拥有全额的投票权利。查看 Conflux Protocol Specification 章节 8.3.2 获取更多信息。

样例

const PRIVATE_KEY = '0xxxxxxx';
const cfx = new Conflux({
  url: 'http://test.confluxrpc.org',
  logger: console,
});
const account = cfx.wallet.addPrivateKey(PRIVATE_KEY); // create account instance

const staking_contract = cfx.InternalContract('Staking');
// deposit some amount of tokens
staking_contract.deposit(your_number_of_tokens).sendTransaction({
  from: account,
}).confirmed();

// withdraw some amount of tokens
staking_contract.withdraw(your_number_of_tokens).sendTransaction({
  from: account,
}).confirmed();

// lock some tokens until some block number
staking_contract.voteLock(your_number_of_tokens, your_unlock_block_number).sendTransaction({
  from: account,
}).confirmed();