Stellar 可用于构建复杂的智能合约。智能合约是基于编程逻辑自动执行协议的计算机程序。
整合技术和法律合同的概念可以追溯到 20 世纪 50 年代,当时学者们建立了在不涉及传统法律程序的情况下执行法律规则的计算方法。智能合约由 Nick Szabo 在 1997 年正式提出并被定义为:
智能合约将协议与用户接口结合起来,它可以安全有效地确定公共网络上的关系。这些系统的设计目标和原则来源于法律原则、经济理论以及可靠和安全的协议理论。
近年来,区块链技术使一种新型的智能合约成为可能,这种合约具有协议条款的不变存储、加密授权和价值的集成转移等特性。
在 Stellar 网络中,智能合约的实现为 Stellar 智能合约(Stellar Smart Contract,SSC)的实现提供了可能。Stellar 智能合约由各种约束和事务组合而成。以下是在创建 Stellar 智能合约时可以考虑和采用的约束示例:
多重签名是指需要多个签名来授权执行事务。签名者的权利用签名权重和阈值来表示。
批处理是指在一个事务中包含多个操作。原子性是指当一个操作执行失败时,事务中的所有操作都将失败。
在事务处理中使用序列号,可以保证在提交二选一的事务不会成功。
时间界限是事务能被顺利提交的时间段。我们可以用它来设置 Stellar 智能合约能被执行的时间范围。
本概述介绍了两种常用的设计模式,可用于在 Stellar 网络上创建智能合约。事务可以直接通过 API 提交,也可以使用 Stellar Laboratory 执行。
注意:恒星网络核心协议正在活跃开发中,所以现在不能保证长期智能合约的前后兼容性。
Ben Bitdiddle 出售 50 CODE 令牌给 Alyssa P. Hacker,条件是 Alyssa 在这一年内不会转售这些令牌。但是 Ben 并不完全信任 Alyssa,所以他建议这些令牌由他代为保管一年。
Alyssa 反对这样做。她无法确信 Ben 在一年之后仍然持有这些令牌,也无法确信一年后 Ben 会将这些令牌发送给她。
此外,Alyssa 记忆力不太好。在长达一年的等待期结束时,她也许会不记得去认领她的令牌。Ben 希望建立一个回收机制,这样只要回收期开始后 Alyssa 还没有认领这些令牌,Ben 就可以回收这些令牌。这样一来,令牌就不会永远丢失了。
在两个实体之间建立了托管协议:资产发送方——托管资金的账户——在合约结束时资产接收方。
在双方之间执行时间锁定的托管合约需要三个账户:源账户,目标账户和托管账户。源账户负责在网络中创建托管账户并向其发送托管资金。目标账户是最终接收托管资金的账户。托管账户由源账户创建,并在锁定期间持有托管资金。
必须为此托管协议商定并确定两个时间段:一个是锁定期,在此期间任何一方都不得操纵(转移,利用)资产;另一个是回收期,在这之后源账户可以从托管账户中回收托管资金。
创建该合约一共用到了 5 笔事务——下面按创建顺序对其进行说明。讲解中将使用以下变量:
对于下面描述的设计模式,要交换的资产是原生资产。向 Stellar 网络提交事务的顺序与创建顺序不同。以下是按时间排列的提交次序:
发起事务的账户:源账户 序列号:M 操作:
签名者:源账户
事务 1 由源账户创建并提交到 Stellar 网络。这样就创建了托管账户,源账户持有者拥有对托管账户的控制权。源账户用网络当前的基本储备金为托管账户提供起始资金,还需要为它提供少量额外的资金以让它能够支付提交事务所需的手续费用。
发起事务的账户:托管账户 序列号:N 操作:
签名者:托管账户
事务 2 由托管账户创建并提交到 Stellar 网络。目前托管账户由发送方控制着。第一个操作将目标账户添加为了签名者,并将它的权重设置为 1。
一般情况下我们将各个等级操作的阈值设置的各不相等,但在这里我们所做的稍有不同。第二个操作将主密钥的权重设置为 1,使其与目标账户的权重相等。在这里,将所有等级操作的阈值设置为 2,因此托管账户提交任何事务都必须得到 2 个权重授权。也就是说在提交这个事务后,托管账户提交任何事务,还需要得到目标账户的授权。
发起事务的账户:托管账户 序列号:N+1 操作:
时间界限(Time Bounds):
先进行签名的账户:托管账户 后进行签名的账户:目标账户
发起事务的账户:托管账户 序列号:N+1 操作:
时间界限(Time Bounds):
先进行签名的账户:托管账户 后进行签名的账户:目标账户
事务 3 和事务 4 由托管账户创建并签署,随后托管账户将生成的事务 3 和事务 4 以 XDR 的形式发送给目标账户,目标账户在审阅该 XDR 后对它进行签名。随后目标账户将签署后的 XDR 发给源账户,源账户审阅该 XDR 后将它们保存在一个安全的地方。一旦这些事务被双方签署,那它们将不能被修改。双方都应该保留这些事务的 XDR 数据,并且可以将它们存储在可公开访问的位置,从而不用担心被篡改。
事务 3 和事务 4 是在源账户向托管账户发送托管资金前被创建和签署的,并且这两个事务具有相同的序列号,这样做是为了确保双方达成了协议。如果在提交这两个事务中的一个之前协议发生了变化,那么发送方和目标账户都需要对托管账户进行授权以执行事务。
事务 3 将托管账户移出了签名者列表,同时修改了阈值,也就是说接收方现在完全控制着托管账户。在锁定时间段结束后,签署托管账户执行的事务所需的唯一账户是目标账户。解锁日期(D+T)是可以提交解锁事务的第一天,如果在这之前提交了事务 3,那么这个事务不会被成功执行。时间上限设为 0 表示该事务不会过期。
事务 4 用于源账户在目标账户未提交解锁事务的情况下回收托管资金。该事务将目标账户移出了签名者列表,同时修改了阈值,现在托管账户只要自己的签名就可以执行事务了,也就是说托管账户现在被发行方控制着。事务 4 可以在回收期(D+T+R)到达后提交,它也不会过期。
事务 3 可以在回收期内的任何时间提交。如果接收方没有提交事务 3 的话,发送方可以提交事务 4 以回收资产到源账户中。如果需要的话,在事务 4 提交之后,源账户可以回收托管账户中锁定的资产,因为它已经不再被需要了。在回收期内,事务 3 和事务 4 都可以被提交到 Stellar 网络,因为它们拥有相同的序列号,所以只有先提交的那个事务会生效。
总结:如果事务 3 没有被目标用户提交,那么发送方可以在回收期到来后提交事务 4。
发起事务的账户:源账户 序列号:M+1 操作:
签名者:源账户
源账户通过事务 5 将适当数量的资产存入托管账户。一旦事务 3 和事务 4 由目标账户签名并发给了源账户,就应该提交该事务。
Alyssa P. Hacker 想要众筹资金来购买一家公司的 Coding Tutorials For Dogs 服务,但她希望通过众筹从公众那里获得资金。如果有足够多的人捐款,她就可以向公司支付服务费用。如果没有,她将通过一个机制来返还捐款。为了保证她对捐赠者的可信赖性和可靠性,她决定询问 Ben Bitdiddle 是否愿意帮助她让人们加入众筹。Ben Bitdiddle 需要向他的朋友们担保 Alyssa 是可信的,以此让他们加入众筹。
在最简单的例子中,众筹智能合约至少需要三方:其中两方(从这里称为甲方和乙方)负责众筹,第三方将获得最终资金(称为目标账户)。在这里我们必须创建一个令牌作为执行众筹的机制。所使用的参与众筹的令牌以及持有账户必须由甲乙两方之一创建。持有账户持有参与令牌,并且可以对该令牌定价。持有账户收取众筹资金,如果在众筹期结束后未达到目标金额,那么资金将会返还给参与者。
创建该合约一共用到了 5 笔事务——下面按创建顺序对其进行说明。讲解中将使用以下变量:
有四个账户用于创建基本的众筹模式。一个是持有账户,这是持有资金和兑换令牌的账户,该账户提交任何事务都需要甲、乙双方授权。第二个是目标账户,这个账户属于提供服务的公司,众筹一旦成功,众筹到的资金会被发送到这个账户。剩下的两个账户分别为甲方和乙方所有,他们负责众筹。
创建此设计模式的事务可以由负责众筹活动的任何一方创建和提交。以下事务是按照创建顺序排列的,提交到恒星网络的顺序取决于众筹活动是否成功。
发起事务的账户:甲方 序列号:M 操作:
签名者:甲方
发起事务的账户:持有账户 序列号:N 操作:
签名者:持有账户
事务 1 和事务 2 由甲方或乙方创建并提交到 Stellar 网络。在事务 1 中,甲方用网络当前的基本储备金为持有账户提供起始资金,一般来说还需要为它提供少量额外的资金以让它能够支付提交事务所需的手续费用。事务 2 将所有等级操作的阈值设置为 2、将主密钥的权重设置为 0、将甲乙双方添加为签名者,同时将它们双方的权重设置为 1,也就是说持有账户提交任何事务都必须得到甲乙双方的授权。这种信任机制是为了保护捐助者免受其中一方恶意行为的伤害。
在事务 2 之后, 持有账户的资金应包括用于众筹活动的令牌, 以及足够的 Lumens 来支付以下所有事务的手续费。
发起事务的账户:持有账户 序列号:N+1 操作:
签名者:甲方账户,乙方账户
创建事务 3 并提交给网络, 以开始众筹活动。它在网络上创建一个订单来出售这些令牌,出售价格为 X。由于令牌的总量是有限的,所以最多可以众筹到资金为 V。
发起事务的账户:持有账户 序列号:N+2 操作:
时间界限(Time Bounds):
签名者:甲方账户,乙方账户
发起事务的账户:持有账户 序列号:N+3 操作:
时间界限(Time Bounds):
签名者:甲方账户,乙方账户
事务 4 和事务 5 是预签名的、未提交的、公开的事务。这两笔事务都设置了能被提交的最早时间,以防止其提交时间不在担保方商定的时间范围内。它们可以由任何人在众筹结束后提交。事务 4 将筹集到的资产发送到目标账户。事务 5 通过取消订单防止剩余的令牌被出售,并创建一个订单回购之前售出的资产,购买价格也应该为 X。
安全性是通过序列号提供的。如上所述,事务 4 的序列号为 N+2,事务 5 的序列号 N+3,这些序列号要求事务 4 和事务 5 以适当的顺序提交到网络。
假设在众筹结束时仍未众筹到足够的资金,也就是说没有售出所有的令牌。事务 4 需要提交到网络,但它将失败。持有账户有足够的 Lumens 来支付事务手续费,因此虽然此事务会因没有足够的资产来支付付款而失败,但是序列号仍然会增大。随后将事务 5 提交到网络,使捐赠者能够使用令牌赎回他们的资产。此外, 事务 5 取消了出售令牌的订单,停止了该众筹。
如果在众筹结束前筹集到数量为 V 的资产,众筹便是成功的。筹集足够的资金意味着所有的参与令牌都被售出了。事务 4 被提交到网络后将会执行成功,因为账户中有足够的资金来完成支付操作。之后如果将事务 5 提交到网络的话,它也会执行成功,但由于持有账户将没有资金来回购令牌,所以捐赠者将无法兑回它们的资金。
如果想要参与众筹,需要执行以下步骤:
当涉及到设计一个智能合约时,当事人必须走到一起,清楚地阐述合同的目的、当事人之间如何合作以及期望的结果。在这个合同中,应该就明确的条件及其结果达成一致。在确定了条件及其结果之后,合同就可以转化为一系列操作和事务。值得注意的是,智能合约是使用代码创建的,但是代码可能包含 bug,也可能不按预期执行。当商定智能合约的条件和结果时,一定要分析并商定所有可能的边缘情况。