智能合约Nervos DAO的存入和取出功能介绍
扫描二维码
随时随地手机看文章
Nervos DAO 是 CKB 经济模型的重要亮点之一,它可以有效的消除二级发行所带来的增发影响,是对抗稀释的一剂良药。一周前,Nervos 团队发布了其 RFC,详细说明了 Nervos DAO 中的存入和取出机制。以下是来自 Nervos 中文社区的部分翻译。我们也期待更多的社区伙伴对 Nervos DAO 进行解读。
动机
Nervos DAO 是一个智能合约,就像 CKB 上其他的智能合约一样,用户可以与之交互。Nervos DAO 的功能之一就是为 CKByte 持币者提供一种抗稀释的功能。通过将 CKByte 存入 Nervos DAO 中,持有者可以获得一定比例的二级发行,在存款和取款之间的这段时间内,他们的持有比例只会受到创世块和基础发行的影响,就像和有硬顶的比特币一样。
持有者可以随时将他们的 CKByte 存入 Nervos DAO 中。Nervos DAO 是一种定期存款,存在一个最短存款期限(会按照区块计算),持有者只能在一个完整的存款期之后进行取款。如果持有者在存款期结束时没有取款,这些 CKByte 将自动进入新的存款周期,这样可以尽量减少持币人的操作次数。
背景
CKB 的发行曲线由两部分组成:
· 基础发行:奖励给矿工的有硬顶的代币发行,使用与比特币相同的发行曲线,约每 4 年减半。
· 二级发行:常量发行,每个难度调节周期(Epoch)都会发行相同数量的 CKByte,这意味着随着时间的推移,二级发行比率将逐渐趋近于零。因为每个 Epoch 内的区块数量是动态调整的,所以每个区块的二级发行会是一个变量。
如果在 CKB 中只有基础发行而没有二级发行,那么 CKByte 的总供应量将会存在一个硬顶,其发行曲线将会和比特币完全一样。为了保障 CKB 的长期持有者不被二级发行稀释,在 Nervos DAO 中锁定的 CKByte 将获得部分比例的二级发行,该比例等于锁定在 Nervos DAO 中的 CKByte 占整个 CKByte 流通量的百分比。
更多关于 Nervos DAO 和 CKB 经济模型的细节,请查看[Nervos RFC #0015]
https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0015-ckb-cryptoeconomics/0015-ckb-cryptoeconomics.md
存款
用户可以随时发送交易将 CKBytes 存入 Nervos DAO。CKB 在创世块中包含一种特殊的 Nervos DAO 类型脚本。想要存储到Nervos DAO 中,只需随时创建一个包含新 Output Cell 的交易,并满足以下要求:
· 创建的 Output Cell 类型脚本必须设置为 Nervos DAO 脚本。
· 该 Output Cell 的 Cell Data 必须有 8 个字节长度,并用 0 将其填充完整。
为方便起见,一个满足上述条件的 Cell 被称为「Nervos DAO 存款单」。为了遵循 CKB 的脚本验证逻辑,存款交易还需要将 Nervos DAO 类型脚本的引用包含在封闭交易的 cell_deps 部分中。注意,在一个交易中,我们不对完整的存款数量进行限制,一个有效的交易中可以创建多个「Nervos DAO 存款单」。
取款
用户可以随时发送交易从 Nervos DAO 中取出已存储的 CKByte(但这里会涉及到一个锁定期来确定什么时候可以取出代币)。一个 Nervos DAO Cell 获得的利息只会在取出阶段发放,这意味着对于一个包含 Nervos DAO 提取交易来说,所有 Onput Cell 的Capacity 总和可能超过所有 Input Cell 的 Capacity 总和。与存款过程不同,从 Nervos DAO 取出需要两个步骤:
· 在第一阶段,第一个交易是将 Nervos DAO 存款单转换为 Nervos DAO 取款单。
· 在第二阶段,第二个交易是从 Nervos DAO 取款单中提取代币。
取款阶段 1
第一阶段是将 Nervos DAO 存款单转换为 Nervos DAO 取款单,这里的目的是确定一个 Cell 存入 Nervos DAO 的时间。一旦第一阶段的交易完成上链,那么就可以通过 Nervos DAO 存款单和 Nervos DAO 取款单之间的持续时间来计算利息,以及计算所存代币的剩余锁定期。
第一阶段的交易应符合下列条件:
· 交易中应包含一个或多个 Nervos DAO 存款单作为输入。
· 对于每个 Nervos DAO 存款单来说,交易需要在 header_deps 中包含对其相关(存款)区块的引用,Nervos DAO 类型脚本将以此作为存款的起点。
· 在 Input 索引 i 中的 Nervos DAO 存款单,应该在 Onput 索引 i 中创建 Nervos DAO 取款单,并满足以下要求:
取款单应该与存款单具有相同的锁定脚本
取款单应该与存款单具有相同的 Nervos DAO 类型脚本
取款单应该与存款单具有相同的 Capacity
取款单也应该有 8 个字节长度的 Cell Data,但不是 8 个零,Cell Data 部分应该存储存款单所在区块的区块数。该数字应该以 64 位未签名小端序整数格式打包。
· Nervos DAO 类型脚本应该包含在取出交易的 cell_deps 中。
一旦该交易完成上链,用户就可以开始准备阶段二的交易了。
取款阶段 2
阶段 2 的交易是从 Nervos DAO 中取出已存的代币和利息。注意,与第一阶段交易不同的是,用户可以在任何时候发送第一阶段的交易,但在第二阶段的交易中,我们将会设置一个「since」字段来实现锁定期的要求,因此,可能会事先只生成一个交易,但是必须等待一段时间后,他/她才可以发送交易到 CKB。
第二阶段的交易应符合以下条件:
· 一个交易应该包含一个或多个 Nervos DAO 取款单作为 Input。
· 对于每个 Nervos DAO 取款单来说,交易需要在 header_deps 中包含对其相关(取款)区块的引用,Nervos DAO 类型脚本将以此作为存款的终点。
· 对于在 Input 索引 i 中的 Nervos DAO 取款单来说,用户应该定位到包含原始 Nervos DAO 存款单的区块头。有了这个存入区块头之后,我们还需要做 2 个操作:
当前交易的 header_deps 中应该包含存入区块头的哈希
header_deps 中存入区块头哈希的索引应该使用 64 位未签名小端序整数格式,并保存在属于相应 Witness 输入 Cell 类型脚本部分的索引 i 中。Witness 当前的论证组织将会在另外一个单独的 RFC 中阐述。下面我们还将通过一个详细的例子来介绍这个过程。
· 对于一个 Nervos DAO 取款单来说,Cell 交易输入中的 since 字段应该反映 Nervos DAO Cell 的锁定周期要求,即 180 个Epoch。例如,如果一个人在第五个 Epoch 存入 Nervos DAO,则他/她只能在第 185、365 或 545 等 Epoch 从 Nervos DAO 中取出。注意,锁定期的计算与利息的计算无关。在第五个 Epoch 存入,在第一百个 Epoch 使用 withdraw block,在第 185 个 Epoch 使用 since 字段是完全有效的。请参考 since RFC (https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0017-tx-valid-since/0017-tx-valid-since.md) 来了解如何表示有效的 Epoch 数,Nervos DAO 类型脚本目前只接受绝对的 Epoch 数作为 since 值。
· 利息计算逻辑完全独立于锁定期限的计算逻辑,我们将在下一节中解释利息计算逻辑。
· Nervos DAO 类型脚本中,所有 Input Cell 的 Capacity 加上利息的总和应该大于或等于所有 Onput Cell 的 Capacity 的总和。
· Nervos DAO 类型脚本应该被包含在 cell_deps 中。
正如上面的步骤所示的那样,在一个交易中执行多个取款是完全有可能的。更重要的是,Nervos DAO 并没有限制提取代币的目的,在同一交易中,将刚提取的代币重新存入 Nervos DAO 中也是有效的。实际上,一个交易可以用来自由地混合以下所有操作:
将代币存入 Nervos DAO 中。
将一些 Nervos DAO 存款单转化为 Nervos DAO 提款单。
从其它 Nervos DAO 中提取 Cell。