金融商品でWavesスマートアカウントとスマートアセットを使用する

画像



前回の記事では、ビジネスでスマートアカウントを使用するいくつかのケース(オークションやロイヤルティプログラムなど)を取り上げました。

今日は、オプション、先物、請求書などの金融商品の透明性と信頼性をスマートアカウントとスマートアセットがどのように向上させるかについて説明します。



オプション



オプションとは、買い手に特定の価格で、または特定の日付より前に資産を購入する権利を与えるが、そうする義務を負わない交換契約です。



オプションの行使は次のとおりです。



オプション自体にはツールとしてスマートアセットを使用し、取引所として機能してオプションを発行する参加者にはスマートアカウントを使用します。 交換メンバーは、expirationStartブロックとexpirationEndブロックの高さの間の価格pricePriceで特定の資産の特定の量を販売することを約束します。



スマートアセットのコードでは、指定された高さの間でのみ取引されていることを確認するだけで、他には何もチェックせず、ルールを遵守する責任は取引所参加者のコードに委ねます。



スマートアセットコード:



let expirationStart = 100000 let expirationEnd = 101440 match tx { case some : ExchangeTransaction | TransferTransaction => height > expirationStart && height <= expirationEnd case _ => false }
      
      





アクションは次のとおりであると仮定します:交換メンバーはいくつかの資産の購入オプションを販売し、残りの参加者はこれらのオプションを転送または取引できます。 購入する権利を行使するために、潜在的な買い手は希望する数のオプションを売り手のアカウント、つまり交換参加者に譲渡する必要があります。 次に、彼は交換メンバーのアカウント状態への完了した転送に関する情報を書き留めます。そうして初めて、ExchangeTransactionは指定された売買条件を通過できます。



スマートアカウントのコードでは、最終的な購入販売行為のために通過するExchangeTransactionが指定された条件を満たしていることを確認する必要があり、参加者は交換参加者のアカウントに送信したユニットの数を正確に購入します。 潜在的なバイヤーは、発生した転送について正しいDataTransactionを送信する必要があります。これにより、交換メンバーは二重支出を回避できます。 このDataTransactionで、買い手は自分の住所に等しいキーに、交換メンバーのアカウントに転送されたオプションの数、つまり購入できる資産ユニットの数に等しい値を設定します。



スマートアカウントコード:



 #         #  sellPrice    expirationStart  expirationEnd let expirationStart = 100000 let expirationEnd = 101440 let sellPrice = 10000 let amountAsset = base58'8jfD2JBLe23XtCCSQoTx5eAW5QCU6Mbxi3r78aNQLcNf' let priceAsset = base58'9jfD2JBLe23XtCCSQoTx5eAW5QCU6Mbxi3r78aNQLcNf' #ID - let optionsAsset = base58'7jfD2JBLe23XtCCSQoTx5eAW5QCU6Mbxi3r78aNQLcNf' #     let this = extract(tx.sender) match tx { case dataTx : DataTransaction => #    -   (ID ) let units = extract(getInteger(dataTx.data, dataTx.data[0].key)) # -    let e = transactionById(dataTx.proofs[2]) # match e { case transferTx : TransferTransaction => #,       (transferTx.recipient == this) && #,         ID dataTx.data[0].key == toBase58String(transferTx.sender.bytes) && sigVerify(dataTx.bodyBytes, dataTx.proofs[0], transferTx.senderPublicKey) && #,         (units == transferTx.amount) && #,     - (transferTx.assetId == optionsAsset) case _ => false } && size(dataTx.data) == 1 && !isDefined(getInteger(this, dataTx.data[0].key)) && height > expirationStart && height <= expirationEnd case order : Order => #,         let correctAssetPair = order.assetPair.amountAsset == amountAsset && order.assetPair.priceAsset == priceAsset let correctPrice = order.price == sellPrice # -   let d = transactionById(order.proofs[2]) match d{ case dataTx : DataTransaction => let buyOrderSender = dataTx.data[0].key toBase58String(order.sender.bytes) == buyOrderSender && order.amount == extract(getInteger(dataTx.data, buyOrderSender)) case _ => false } && order.sender == this && correctAssetPair && correctPrice && height > expirationStart && height <= expirationEnd case _ => false }
      
      





スマートアカウント先物



オプションとは異なり、先物(先物契約)は権利ではなく、将来のある時点で固定価格で資産を購入する買い手の義務です。



一般的に、先物の実装はオプションの実装に似ています。 ここで、スマートアセットは先物として機能します。



また、買い手と売り手の両方が注文書に署名することを確認する必要があります。 先物は、いかなる場合でも満たされなければならない義務です。 これは、売り手または参加者が義務を放棄した場合、どのネットワーク参加者も取引を送信できるため、先物を実行できることを意味します。



スマートアセットスクリプトは、TransferTransactionおよびExchangeTransaction Asset Futuresをすべて制御し、購入メンバーがExchangeメンバーからAsset Futuresを将来購入するための注文を作成した場合にのみ承認します。



この注文は有効であり、先物が発行される条件を満たしている必要があります。 注文を確認するには、署名された注文のバイト表現とともに買い手のアカウントの状態ですべてのフィールドを入力し、外部から検証できます。



現時点では、RIDEにはトランザクションバイトを解析するためのネイティブ関数は含まれていませんが、その実装に必要なすべてのツールが含まれています。 したがって、開発者は自分でこの機能を実装することができます。



マルチサインアカウント/エスクロー



マルチ署名のアカウントでは、複数のユーザーが資産を共同で管理できます(たとえば、資産を持つトランザクションは、4人のユーザーのうち3人の署名がある場合にのみ可能です)。 RIDE言語でマルチ署名を持つアカウントを作成するには、トランザクション証明を使用できます。



マルチ署名のアカウントはエスクローアカウントにも使用できます。エスクローアカウントでは、契約の当事者が義務を果たすまで資金が保存されます。



 let alicePubKey = base58'5AzfA9UfpWVYiwFwvdr77k6LWupSTGLb14b24oVdEpMM' let bobPubKey = base58'2KwU4vzdgPmKyf7q354H9kSyX9NZjNiq4qbnH2wi2VDF' let cooperPubKey = base58'GbrUeGaBfmyFJjSQb9Z8uTCej5GzjXfRDVGJGrmgt5cD' #,     let aliceSigned = if(sigVerify(tx.bodyBytes, tx.proofs[0], alicePubKey)) then 1 else 0 let bobSigned = if(sigVerify(tx.bodyBytes, tx.proofs[1], bobPubKey)) then 1 else 0 let cooperSigned = if(sigVerify(tx.bodyBytes, tx.proofs[2], cooperPubKey)) then 1 else 0 #        aliceSigned + bobSigned + cooperSigned >= 2
      
      





トークン管理レジストリ(TCR)



多くのブロックチェーンプラットフォームでは、有毒資産の問題があります。 たとえば、コミッションを支払った住所は、Wavesでアセットを作成できます。



トークンホルダーによって生成されたトークンキュレーションレジストリ(TCR)は、有害な資産からユーザーとブロックチェーンを保護する問題の解決に役立ちます。



特定のトークンをリストに追加するために投票するために、所有者は、発行された総数のトークンの自分のシェアに等しい賭けをします。 ほとんどの所有者がトークンに投票した場合、トークンはレジストリに含まれます。



この例では、現在の値がcount = 0の場合にのみ、キーキーasset = asset_nameによって(「チャレンジ」期間中)ユーザーがリストにトークンを追加できるようにします。



また、ウォレットのユーザーは、このトークンの残高がゼロ以外である必要があります。 次に、ユーザーが自分のウォレット内の各アセットに投票することができる投票期間が来ますが、1〜10の評価を与えます。ユーザーの声は、user_address + assetIDの形式のキーで表されます。



 let asset = base58'8jfD2JBLe23XtCCSQoTx5eAW5QCU6Mbxi3r78aNQLcNf' let addingStartHeight = 1000 let votingStartHeight = 2000 let votingEndHeight = 3000 let this = extract(tx.sender) #     let address = addressFromPublicKey(tx.proofs[1]) match tx { case t: DataTransaction => if(height > addingStartHeight) then( if(height < votingStartHeight) then( #adding #,        let hasTokens = assetBalance(address, asset) > 0 size(t.data) == 1 #,        && !isDefined(getInteger(this, toBase58String(asset))) #,   -    0 && extract(getInteger(t.data, toBase58String(asset))) == 0 && hasTokens ) else( if(height < votingEndHeight) then ( #voting #          let currentAmount = extract(getInteger(this, toBase58String(asset))) let newAmount = extract(getInteger(t.data, toBase58String(asset))) let betString = toBase58String(address.bytes) + toBase58String(asset) #,          let noBetBefore = !isDefined(getInteger(this, betString)) let isBetCorrect = extract(getInteger(t.data, betString)) > 0 && extract(getInteger(t.data, betString)) <= 10 #,       let hasTokens = assetBalance(address, asset) > 0 #    size(t.data) == 2 && isDefined(getInteger(this, toBase58String(asset))) && newAmount == currentAmount + 1 && noBetBefore && isBetCorrect && hasTokens ) else false ) && sigVerify(tx.bodyBytes, tx.proofs[0], tx.proofs[1]) ) else false case _ => false }
      
      





購読料



この例では、スマートアカウントを使用して、所定の間隔(「月額料金」)で製品またはサービスの定期的な支払いを行うことを検討します。

ユーザーが、必要な金額の資金を送金したID TransferTransactionを(取引証明を通じて)スマートアカウントに提供する場合、アカウント状態に{key:address、value: true }を書き込むことができます。



これは、ユーザーが製品またはサービスのサブスクリプションを確認することを意味します。 サブスクリプションの有効期限が切れると、すべてのネットワークユーザーがステータスの対応するキーをfalseに設定できます



 let subscriptionPeriod = 44000 let signature = tx.proofs[0] let pk = tx.proofs[1] let requiredAmount = 100000 let this = extract(tx.sender) match tx { case d: DataTransaction => #    let lastPaymentHeight = extract(getInteger(this, d.data[0].key + "_lastPayment")) size(d.data) == 1 && d.data[0].value == "false" && lastPaymentHeight + subscriptionPeriod < height || ( let address = d.data[0].key # -  ID,    let ttx = transactionById(d.proofs[0]) size(d.data) == 2 && d.data[0].value == "true" && d.data[1].key == address + "_lastPayment" && match ttx { case purchase : TransferTransaction => d.data[1].value == transactionHeightById(purchase.id) && toBase58String(purchase.sender.bytes) == address && purchase.amount == requiredAmount && purchase.recipient == this #,   waves && !isDefined(purchase.assetId) case _ => false } ) case _ => false }
      
      





投票



スマートアカウントを使用して、ブロックチェーンに投票を実装できます。 例としては、アンバサダープログラムの枠組みの中で最高のアンバサダーレポートへの投票があります。 アカウント状態は、1つまたは別のオプションの投票を記録するためのプラットフォームとして使用されます。



この例では、特別な「投票」トークンを購入した人にのみ投票が許可されます。 参加者は、(キー、値)=(purchaseTransactionId、buyTransactionId)のペアで事前にDataTransactionを送信します。 このキーに異なる値を設定することは禁止されています。 アドレスと投票オプションを使用して、DataEntryを1回だけインストールできます。 投票は設定された期間のみ可能です。



 let asset = base58'8jfD2JBLe23XtCCSQoTx5eAW5QCU6Mbxi3r78aNQLcNf' let address = addressFromPublicKey(tx.proofs[1]) let votingStartHeight = 2000 let votingEndHeight = 3000 let this = extract(tx.sender) match tx { case t: DataTransaction => (height > votingStartHeight && height < votingEndHeight) && #,      sigVerify(tx.bodyBytes, tx.proofs[0], tx.proofs[1]) && #,         if (t.data[0].key == toBase58String(address.bytes)) then ( #       let purchaseTx = transactionById(t.proofs[7]) match purchaseTx { case purchase : TransferTransaction => let correctSender = purchase.sender == t.sender let correctAsset = purchase.assetId == asset let correctPrice = purchase.amount == 1 let correctProof = extract(getBinary(this, toBase58String(purchase.id))) == t.id correctSender && correctAsset && correctPrice && correctProof case _ => false } ) else size(t.data) == 1 && !isDefined(getBinary(this, t.data[0].key)) case _ => false }
      
      





手形



手形とは、要求時または所定の日付に一方の当事者が他方に一定額を支払わなければならない書面による義務です。



この例では、有効期限が請求書の支払い日に対応するスマートアカウントが使用されます。



 let expiration = 100000 let amount = 10 let asset = base58'9jfD2JBLe23XtCCSQoTx5eAW5QCU6Mbxi3r78aNQLcNf' let Bob = Address(base58'3NBVqYXrapgJP9atQccdBPAgJPwHDKkh6A8') let Alice = Address(base58'3PNX6XwMeEXaaP1rf5MCk8weYeF7z2vJZBg') match tx { case t: TransferTransaction => (t.assetId == asset)&& (t.amount == amount)&& (t.sender == Bob)&& (t.recipient == Alice)&& (sigVerify(t.bodyBytes, t.proofs[0], t.senderPublicKey))&& (height >= expiration) case _ => false }
      
      





入金



預金-特定の条件(期間、割合)での銀行への資金の配置。

この例では、銀行の機能はスマートアカウントによって実行されます。 預金の期間に対応する一定数のブロックの後、ユーザーはパーセンテージで自分のお金を返すことができます。 スクリプトはブロックの高さ(finalHeight)を設定します。その後、ユーザーはアカウントからお金を引き出すことができます。



heightUnit-1単位の時間内のブロック数(たとえば、月、年など)。 最初に、ペア(キー、値)=(initialTransferTransaction、futureDataTransaction)を持つエントリをチェックします。 次に、ユーザーはTransferTransactionに、デポジットの金額とデポジット期間中に発生した利息に関する正しい情報を送信する必要があります。 この情報は、現在のTransferTransactionプルーフに含まれている元のTransferTransactionに対してチェックされます。 depositDivisor-デポジットのシェアの逆数(デポジットが10%で受け入れられる場合、デポジットのシェアは0.1であり、depositDevisor = 1 / 0.1 = 10)。



 let depositDivisor = 10 let heightUnit = 1000 let finalHeight = 100000 let this = extract(tx.sender) match tx { case e : TransferTransaction => #    ID     let depositHeight = extract(transactionHeightById(e.proofs[7])) #   let purchaseTx = transactionById(e.proofs[7]) match purchaseTx { case deposit : TransferTransaction => let correctSender = deposit.sender == e.sender #,        +  let correctAmount = deposit.amount + deposit.amount / depositDivisor * (height - depositHeight) / heightUnit == e.amount let correctProof = extract(getBinary(this, toBase58String(deposit.id))) == e.id correctSender && correctProof && correctAmount case _ => false } && finalHeight <= height case _ => sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey) }
      
      





このシリーズの3番目の最終記事では、特定のアドレスのトランザクションの凍結や制限など、スマートアセットを使用するためのその他のオプションについて説明します。



All Articles