使用Waves智能帐户:从拍卖到奖金计划

图片

区块链通常仅与加密货币相关联,但DLT技术的范围要广泛得多。 使用区块链最有前途的领域之一是自动运行的智能合约,不需要缔约双方之间的信任。

RIDE-智能合约的语言

Waves为智能合约开发了一种特殊的语言-RIDE。 它的完整文档在这里 。 在这里-有关哈布雷的主题的文章

RIDE上的合同是一个谓词,在输出中返回“ true”或“ false”。 因此,交易被写入区块链或被拒绝。 智能合约可充分保证满足指定条件。 目前无法从RIDE中的合同生成交易。

如今,Waves智能合约有两种类型:智能帐户和智能资产。 智能帐户是普通用户帐户,但是为它设置了控制所有交易的脚本。 智能帐户脚本可能如下所示:

match tx { case t: TransferTransaction | MassTransferTransaction => false case _ => true } 

tx是已处理的交易,只有在它不是转移交易时,我们才允许使用模式匹配机制。 RIDE模式匹配用于验证交易类型。 在智能帐户脚本中,可以处理所有现有交易类型

此外,可以在脚本中声明变量,可以使用“ if-then-else”构造和用于全面检查条件的其他方法。 为了使合同具有可证明的完成性和复杂性(成本)(在合同开始之前易于预测),RIDE不包含循环和跳转之类的运算符。

Waves帐户的其他功能之一是“状态”的存在,即帐户的状态。 可以使用数据事务(DataTransaction)将无数对(键,值)写入帐户状态。 此外,可以通过REST API以及直接在智能合约中处理此信息。

每笔交易都可以包含一系列的证明,您可以在其中输入参与者的签名,必要交易的ID等。

通过IDE使用RIDE,可以查看合同的编译形式(如果已编译),创建新帐户并为其设置脚本以及通过命令行发送交易。

在一个完整的周期中,包括创建一个帐户,在其上安装智能合约并发送交易,您还可以使用该库与REST API交互(例如,C#,C,Java,JavaScript,Python,Rust,Elixir)。 要开始使用IDE,只需单击“新建”按钮。

使用智能合约的可能性非常广泛:从禁止交易到某些地址(“黑名单”)再到复杂的dApp。

现在,让我们看一下在企业中使用智能合约的特定示例:在拍卖,保险和建立忠诚度计划期间。

拍卖会

拍卖成功的条件之一就是透明度:投标人必须确保不可能操纵投标。 这要归功于区块链,所有赌注的未更改数据及其生成时间将对所有参与者可用。

在Waves区块链上,可以通过DataTransaction将出价记录在拍卖帐户状态中。

您还可以使用区块编号设置拍卖的开始和结束时间:Waves区块链中的区块生成频率约为60秒。

1.英语拍卖价格上涨

参加英国竞标的参与者相互竞争。 每个新的下注必须超过前一个。 当没有其他人愿意超过最后的出价时,拍卖结束。 在这种情况下,最高出价者必须提供声明的金额。

还有一个拍卖选项,其中卖方设定最低价格,而最终价格必须超过该最低价格。 否则,该批次仍未售出。

在此示例中,我们使用专门为拍卖创建的帐户。 拍卖的持续时间为3000块,该批次的初始价格为0.001 WAVES。 参与者可以通过发送带有“价格”键和其出价的值的DataTransaction进行下注;在交易证明中,您需要添加公共密钥和发送者的签名。

新投注的价格应高于此密钥的当前价格,并且参与者必须在帐户中至少具有[new_state + Commission]令牌。 必须在DataTransaction的“发件人”字段中输入出价人的地址,并且当前出价区高度必须在拍卖期内。

如果投标人在拍卖结束时设置了最高价格,则他可以发送ExchangeTransaction以指定的价格和货币对支付相应的手数。

 let startHeight = 384120 let finishHeight = startHeight + 3000 let startPrice = 100000 #     let this = extract(tx.sender) let token = base58'8jfD2JBLe23XtCCSQoTx5eAW5QCU6Mbxi3r78aNQLcNf' match tx { case d : DataTransaction => #,      let currentPrice = if isDefined(getInteger(this, "price")) #    then extract(getInteger(this, "price")) else startPrice #    let newPrice = extract(getInteger(d.data, "price")) #       let pk = d.proofs[1] let address = addressFromPublicKey(pk) let priceIsBigger = newPrice > currentPrice let fee = 700000 let hasMoney = wavesBalance(address) + fee >= newPrice let correctFields = size(d.data) == 2 && extract(getString(d.data, "sender")) == toBase58String(address.bytes) startHeight <= height && height <= finishHeight && priceIsBigger && hasMoney && correctFields && sigVerify(tx.bodyBytes, tx.proofs[0], tx.proofs[1]) case o : Order => #       let pk = o.proofs[1] let address = addressFromPublicKey(pk) let senderIsWinner = address == addressFromString(extract(getString(this, "sender"))) #,    ,    let correctAssetPair = o.assetPair.amountAsset == token && ! isDefined(o.assetPair.priceAsset) let correctAmount = o.amount == 1 let correctPrice = o.price == extract(getInteger(this, "price")) height > finishHeight && senderIsWinner && correctAssetPair && correctAmount && correctPrice && sigVerify(o.bodyBytes, o.proofs[0], o.proofs[1]) case _ => false } 

2.荷兰拍卖行情下跌

在荷兰的拍卖中,最初提供的价格高于买方愿意支付的价格。 价格会逐步降低,直到其中一位参与者同意以当前价格购买该批产品为止。

在此示例中,我们使用与上一个相同的常量,以及降低增量时的价格步长。 帐户脚本检查参与者是否真的是第一个下注的人。 在交易证明中,需要添加公钥和发送者的签名,否则,区块链不接受DataTransaction。

 let startHeight = 384120 let finishHeight = startHeight + 3000 let startPrice = 100000000 let delta = 100 #     let this = extract(tx.sender) let token = base58'8jfD2JBLe23XtCCSQoTx5eAW5QCU6Mbxi3r78aNQLcNf' match tx { case d : DataTransaction => let currentPrice = startPrice - delta * (height - startHeight) #   -  "price" let newPrice = extract(getInteger(d.data, "price")) #       let pk = d.proofs[1] let address = addressFromPublicKey(pk) let correctFields = extract(getString(d.data, "sender")) == toBase58String(address.bytes) && size(d.data) == 2 && newPrice == currentPrice #,         "sender" let noBetsBefore = !isDefined(getInteger(this, "sender")) let fee = 700000 let hasMoney = wavesBalance(address) - fee >= newPrice startHeight <= height && height <= finishHeight && noBetsBefore && hasMoney && correctFields && sigVerify(tx.bodyBytes, tx.proofs[0], tx.proofs[1]) case o : Order => #       let pk = o.proofs[1] let address = addressFromPublicKey(pk) #,           sender let senderIsWinner = address == addressFromString(extract(getString(this, "sender"))) #,  mount   ,   - - waves let correctAssetPair = o.assetPair.amountAsset == token && ! isDefined(o.assetPair.priceAsset) let correctAmount = o.amount == 1 let correctPrice = o.price == extract(getInteger(this, "price")) height > finishHeight && senderIsWinner && correctAssetPair && correctAmount && correctPrice && sigVerify(o.bodyBytes, o.proofs[0], o.proofs[1]) case _ => false } 

3.全薪拍卖

“全额付款”-拍卖,所有参与者均支付竞标价,无论谁中了谁。 每个新参与者都下注,最大赌注的参与者将赢得很多。

在我们的示例中,每个拍卖参与者都通过DataTransaction使用(键,值)* =(“获胜者”,地址),(“价格”,价格)进行出价。 仅当此参与者已经存在带有签名的TransferTransaction并且其速率高于所有以前的Transtrans时,才批准此类DataTransaction。 拍卖将持续到达到endHeight。

 let startHeight = 1000 let endHeight = 2000 let token = base58'8jfD2JBLe23XtCCSQoTx5eAW5QCU6Mbxi3r78aNQLcNf' match tx { case d: DataTransaction => #   -  "price" let newPrice = extract(getInteger(d.data, "price")) #       let pk = d.proofs[1] let address = addressFromPublicKey(pk) #        let proofTx = extract(transactionById(d.proofs[2])) height > startHeight && height < endHeight && size(d.data) == 2 #,   ,    ,   ,    && extract(getString(d.data, "winner")) == toBase58String(address.bytes) && newPrice > extract(getInteger(this, "price")) #,    && sigVerify(d.bodyBytes, d.proofs[0], d.proofs[1]) #  ,    && match proofTx { case tr : TransferTransaction => tr.sender == address && tr.amount == newPrice case _ => false } case t: TransferTransaction => sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey) || ( height > endHeight && extract(getString(this, "winner")) == toBase58String((addressFromRecipient(t.recipient)).bytes) && t.assetId == token && t.amount == 1 ) case _ => sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey) } 

保险/众筹

考虑一种情况,您需要确保用户资产免受财务损失。 例如,用户希望获得保证,如果代币贬值,他将能够退还为这些代币支付的全部金额,并准备支付合理的保险金额。

为此,您需要发行“保险令牌”。 然后,在保单持有人的帐户上安装了一个脚本,该脚本允许您仅执行那些满足某些条件的ExchangeTransactions。

为了防止重复支出,您需要请求用户使用(key,value)=(purchaseTransactionId,sellOrderId)将DataTransaction预先发送到保单持有人帐户,并禁止发送已经使用过的密钥的DataTransactions。

因此,用户的证明必须包含购买保险令牌的交易ID。 货币对必须与购买交易中的货币对相同。 费用也应等于购买时记录的费用减去保险价格。

可以理解,随后保险账户以不低于其购买价格的价格从用户赎回保险令牌:保险账户创建ExchangeTransaction,用户签署订单(如果交易正确完成),保险账户签署第二笔订单和整个交易并将其发送到区块链。

如果未发生购买,则用户可以根据脚本中描述的规则创建订单,然后将交易发送到区块链。 因此,用户可以退还用于购买保险代币的钱。

 let insuranceToken = base58'8jfD2JBLe23XtCCSQoTx5eAW5QCU6Mbxi3r78aNQLcNf' #     let this = extract(tx.sender) let freezePeriod = 150000 let insurancePrice = 10000 match tx { #, ,   -,              case d : DataTransaction => size(d.data) == 1 && !isDefined(getBinary(this, d.data[0].key)) case o : Order => #     ,    if !isDefined(o.proofs[7]) then sigVerify(o.bodyBytes, o.proofs[0], o.senderPublicKey) else #     ,         let purchaseTx = transactionById(o.proofs[7]) let purchaseTxHeight = extract(transactionHeightById(o.proofs[7])) #    match purchaseTx { case purchase : ExchangeTransaction => let correctSender = purchase.sender == o.sender let correctAssetPair = o.assetPair.amountAsset == insuranceToken && purchase.sellOrder.assetPair.amountAsset == insuranceToken && o.assetPair.priceAsset == purchase.sellOrder.assetPair.priceAsset let correctPrice = o.price == purchase.price - insurancePrice && o.amount == purchase.amount let correctHeight = height > purchaseTxHeight + freezePeriod #,   -   ID   let correctProof = extract(getBinary(this, toBase58String(purchase.id))) == o.id correctSender && correctAssetPair && correctPrice && correctHeight && correctProof case _ => false } case _ => sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey) } 

可以将保险令牌设为智能资产,例如,禁止将其转让给第三方。

该方案还可以用于众筹令牌,如果尚未收集到必要的数量,则将其返还给所有者。

交易税

智能合约也适用于需要从具有多种资产类型的每笔交易中征税的情况。 这可以通过使用智能资产进行交易的新赞助资产来完成:

1.我们发布了FeeCoin,它将以固定价格发送给用户:0.01 WAVES = 0.001 FeeCoin。

2.我们为FeeCoin和汇率设置了赞助:0.001 WAVES = 0.001 FeeCoin。

3.我们为智能资产设置以下脚本:

 let feeAssetId = base58'8jfD2JBLe23XtCCSQoTx5eAW5QCU6Mbxi3r78aNQLcNf' let taxDivisor = 10 match tx { case t: TransferTransaction => t.feeAssetId == feeAssetId && t.fee == t.amount / taxDivisor case e: ExchangeTransaction| MassTransferTransaction => false case _ => true } 

现在,每次有人转让N项智能资产时,他都会给您FeeCoin N / taxDivisor(可以从您那里以10 * N / taxDivisor WAVES的价格购买)的价格给您,而您将给矿工N / taxDivisor WAVES。 结果,您的利润(税)为9 * N / taxDivisor WAVES。

您还可以使用智能资产脚本和MassTransferTransaction征税:

 let taxDivisor = 10 match tx { case t : MassTransferTransaction => let twoTransfers = size(t.transfers) == 2 let issuerIsRecipient = t.transfers[0].recipient == addressFromString("3MgkTXzD72BTfYpd9UW42wdqTVg8HqnXEfc") let taxesPaid = t.transfers[0].amount >= t.transfers[1].amount / taxDivisor twoTransfers && issuerIsRecipient && taxesPaid case _ => false } 

现金返还和会员计划

现金返还是一种忠诚度计划,其中将在产品或服务上花费的部分金额返还给买方。

使用智能帐户实施此案例时,我们必须像在保险案例中一样检查证明。 为了防止重复支出,用户必须在收到现金返还之前发送(key,value)=(purchaseTransactionId,cashbackTransactionId)的DataTransaction。

我们还必须使用DataTransaction禁止现有密钥。 CashbackDivisor-单位除以现金返还份额。 即 如果现金返还份额为0.1,则CashbackDivisor 1 / 0.1 = 10。

 let cashbackToken = base58'8jfD2JBLe23XtCCSQoTx5eAW5QCU6Mbxi3r78aNQLcNf' #     let this = extract(tx.sender) let cashbackDivisor = 10 match tx { #, ,   -,              case d : DataTransaction => size(d.data) == 1 && !isDefined(getBinary(this, d.data[0].key)) case e : TransferTransaction => #     ,    if !isDefined(e.proofs[7]) then sigVerify(e.bodyBytes, e.proofs[0], e.senderPublicKey) else #     ,         let purchaseTx = transactionById(e.proofs[7]) let purchaseTxHeight = extract(transactionHeightById(e.proofs[7])) #    match purchaseTx { case purchase : TransferTransaction => let correctSender = purchase.sender == e.sender let correctAsset = e.assetId == cashbackToken let correctPrice = e.amount == purchase.amount / cashbackDivisor #,   -   ID   let correctProof = extract(getBinary(this, toBase58String(purchase.id))) == e.id correctSender && correctAsset && correctPrice && correctProof case _ => false } case _ => sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey) } 

原子交换

原子交换使用户无需交换即可交换资产。 在原子交换中,交易的两个参与者都需要在一定时间内进行确认。

如果至少一位参与者未在分配给交易的时间内提供正确的交易确认,则交易将被取消,并且不会进行任何交易。

在我们的示例中,我们将使用以下智能帐户脚本:

 let Bob = Address(base58'3NBVqYXrapgJP9atQccdBPAgJPwHDKkh6A8') let Alice = Address(base58'3PNX6XwMeEXaaP1rf5MCk8weYeF7z2vJZBg') let beforeHeight = 100000 let secret = base58'BN6RTYGWcwektQfSFzH8raYo9awaLgQ7pLyWLQY4S4F5' match tx { case t: TransferTransaction => let txToBob = t.recipient == Bob && sha256(t.proofs[0]) == secret && 20 + beforeHeight >= height let backToAliceAfterHeight = height >= 21 + beforeHeight && t.recipient == Alice txToBob || backToAliceAfterHeight case _ => false } 

在下一篇文章中,我们将考虑在金融工具(例如期权,期货和票据)中使用智能帐户。

Source: https://habr.com/ru/post/zh-CN442238/


All Articles