In einem früheren Artikel haben wir uns mit mehreren Fällen der Verwendung von Smart Accounts in Unternehmen befasst - einschließlich Auktionen und Treueprogrammen.
Heute werden wir darüber sprechen, wie intelligente Konten und intelligente Vermögenswerte die Transparenz und Zuverlässigkeit von Finanzinstrumenten wie Optionen, Futures und Rechnungen erhöhen können.
OptionEine Option ist ein Umtauschvertrag, der dem Käufer das Recht gibt, einen Vermögenswert zu einem bestimmten Preis oder vor einem bestimmten Datum zu kaufen, ihn jedoch nicht dazu verpflichtet.
Die Ausübung der Option kann wie folgt erfolgen:
Wir verwenden ein Smart Asset für die Optionen selbst als Tool und ein Smart Account für den Teilnehmer, der als Austausch fungiert und Optionen ausgibt. Das Börsenmitglied verspricht, einen bestimmten Betrag eines bestimmten Vermögenswerts zum Preis zu verkaufen (Verkaufspreis zwischen den Höhen der Blöcke expirationStart und expirationEnd).
Im Code des Smart Assets überprüfen wir einfach, ob es nur zwischen den angegebenen Höhen gehandelt wird, und wir überprüfen nichts anderes. Wir überlassen die gesamte Verantwortung für die Einhaltung der Regeln dem Code des Börsenteilnehmers.
Smart Asset Code:let expirationStart = 100000 let expirationEnd = 101440 match tx { case some : ExchangeTransaction | TransferTransaction => height > expirationStart && height <= expirationEnd case _ => false }
Wir gehen davon aus, dass die Aktionen wie folgt sind: Das Börsenmitglied verkauft Optionen für den Kauf eines Vermögenswerts, und der Rest der Teilnehmer kann diese Optionen übertragen oder handeln. Um von seinem Kaufrecht Gebrauch zu machen, muss ein potenzieller Käufer die gewünschte Anzahl von Optionen auf das Konto des Verkäufers, dh des Börsenteilnehmers, übertragen. Anschließend schreibt er Informationen über die abgeschlossene Überweisung in den Kontostatus des Exchange-Mitglieds und erst dann kann ExchangeTransaction die angegebenen Kauf- und Verkaufsbedingungen durchlaufen.
Im Code des Smart-Kontos müssen wir sicherstellen, dass jede ExchangeTransaction, die für den endgültigen Kauf-Verkaufs-Vorgang durchlaufen wird, die angegebenen Bedingungen erfüllt und der Teilnehmer genau die Anzahl der Einheiten kauft, die er auf das Konto des Exchange-Teilnehmers gesendet hat. Ein potenzieller Käufer muss die korrekte DataTransaction über die Übertragung senden, damit das Austauschmitglied doppelte Ausgaben vermeiden kann. Bei dieser DataTransaction legt der Käufer einen Schlüssel an, der seiner Adresse entspricht. Dies entspricht der Anzahl der Optionen, die auf das Konto des Börsenmitglieds übertragen wurden, dh der Anzahl der Asset-Einheiten, die er kaufen kann.Smart Account Code: # # 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 }
Smart Account FuturesIm Gegensatz zu einer Option sind Futures (Futures-Kontrakte) kein Recht, sondern die Verpflichtung des Käufers, einen Vermögenswert zu einem bestimmten Zeitpunkt in der Zukunft zu einem festen Preis zu kaufen.
Im Allgemeinen ähnelt die Implementierung der Futures der Implementierung einer Option. Hier fungiert ein Smart Asset als Futures.
Sie müssen auch sicherstellen, dass sowohl der Käufer als auch der Verkäufer die Bestellung unterschreiben. Futures ist eine Verpflichtung, die in jedem Fall erfüllt werden muss. Dies bedeutet, dass jeder Netzwerkteilnehmer, wenn ein Verkäufer oder ein Teilnehmer seine Verpflichtungen ablehnt, eine Transaktion senden und so Futures ausführen kann.
Das Smart Asset Script steuert alle TransferTransaction- und ExchangeTransaction-Asset-Futures und genehmigt sie nur, wenn das kaufende Mitglied eine Bestellung für den zukünftigen Kauf von Asset-Futures vom Exchange-Mitglied erstellt hat.
Diese Bestellung muss gültig sein und die Bedingungen erfüllen, unter denen die Futures ausgegeben werden. Um eine Bestellung zu überprüfen, können Sie alle Felder zusammen mit der Byte-Darstellung der unterschriebenen Bestellung in den Status des Käuferkontos eingeben und dann von außen validieren.
Derzeit enthält RIDE keine native Funktion zum Parsen von Transaktionsbytes, sondern alle für die Implementierung erforderlichen Tools. Daher können Entwickler versuchen, diese Funktion selbst zu implementieren.
Multi-Signed Account / EscrowEin Konto mit einer Mehrfachsignatur ermöglicht es mehreren Benutzern, Assets gemeinsam zu verwalten (Transaktionen mit Assets können beispielsweise nur möglich sein, wenn drei von vier Benutzern Signaturen haben). Um Konten mit Mehrfachsignatur in der RIDE-Sprache zu erstellen, können wir Transaktionsnachweise verwenden.
Ein Konto mit einer Mehrfachsignatur kann auch für ein Treuhandkonto verwendet werden, auf dem das Geld gespeichert wird, bis die Vertragsparteien ihren Verpflichtungen nachkommen.
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
Token-Managed Registry (TCR)Auf vielen Blockchain-Plattformen besteht das Problem toxischer Vermögenswerte. Beispielsweise kann jede Adresse, die eine Provision gezahlt hat, ein Asset auf Waves erstellen.
Die von Token-Inhabern generierte Token Curated Registry (TCR) hilft bei der Lösung des Problems des Schutzes von Benutzern und der Blockchain vor toxischen Assets.
Um für das Hinzufügen eines bestimmten Tokens zur Liste zu stimmen, setzt der Inhaber seinen Einsatz von Token an der Gesamtzahl der ausgegebenen Token. Ein Token wird in die Registrierung aufgenommen, wenn die meisten Inhaber dafür gestimmt haben.
In unserem Beispiel erlauben wir dem Benutzer, das Token der Liste zur Prüfung (während des "Herausforderungszeitraums") durch den Schlüssel des Status "Schlüssel = Asset-Name" hinzuzufügen, nur wenn der aktuelle Wert count = 0 ist.
Außerdem muss der Benutzer in der Brieftasche einen Kontostand ungleich Null für dieses Token haben. Dann folgt der Abstimmungszeitraum, in dem der Benutzer für jedes Asset in seiner Brieftasche eine Stimme abgeben kann, jedoch nur einmal, was eine Bewertung von 1 bis 10 ergibt. Die Stimmen der Benutzer werden durch Schlüssel der Form Benutzeradresse + Asset-ID dargestellt.
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 }
AbonnementgebührIn diesem Beispiel wird die Verwendung von Smart Accounts in Betracht gezogen, um regelmäßige Zahlungen für ein Produkt oder eine Dienstleistung in festgelegten Intervallen zu leisten - eine „monatliche Gebühr“.
Wenn ein Benutzer ein Smart-Konto (durch Transaktionsnachweise) mit einer ID TransferTransaction mit dem erforderlichen Überweisungsbetrag bereitstellt, kann er {Schlüssel: Adresse, Wert:
Wahr } in den Kontostatus schreiben.
Dies bedeutet, dass der Benutzer das Abonnement für das Produkt oder die Dienstleistung bestätigt. Wenn das Abonnement abläuft, kann jeder Netzwerkbenutzer den entsprechenden Schlüssel im Status auf
false setzen .
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 }
AbstimmungIntelligente Konten können verwendet werden, um Abstimmungen in der Blockchain zu implementieren. Ein Beispiel wäre eine Abstimmung für den besten Botschafterbericht im Rahmen des Botschafterprogramms. Der Kontostatus wird als Plattform zum Aufzeichnen von Stimmen für die eine oder andere Option verwendet.
In diesem Beispiel ist die Abstimmung nur für diejenigen zulässig, die spezielle Abstimmungsmarken gekauft haben. Der Teilnehmer sendet im Voraus eine DataTransaction mit einem Paar von (Schlüssel, Wert) = (purchaseTransactionId, buyTransactionId). Das Festlegen eines anderen Werts für diesen Schlüssel ist nicht zulässig. Mit Ihrer Adresse und Abstimmungsoption können Sie DataEntry nur einmal installieren. Abstimmungen sind nur während des festgelegten Zeitraums möglich.
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 }
WechselEin Wechsel ist eine schriftliche Verpflichtung, nach der eine Partei der anderen Partei zum Zeitpunkt des Antrags oder zu einem festgelegten Zeitpunkt einen festen Betrag zahlen muss.
In unserem Beispiel wird ein Smart Account verwendet, dessen Ablaufdatum dem Zahlungsdatum der Rechnung entspricht.
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 }
KautionEinzahlung - Platzierung von Geldern bei einer Bank unter bestimmten Bedingungen (Laufzeit, Prozentsatz).
In unserem Beispiel erfüllt ein Smart Account die Funktion einer Bank. Nach einer bestimmten Anzahl von Blöcken, die der Laufzeit der Einzahlung entspricht, kann der Benutzer sein Geld mit einem Prozentsatz zurückgeben. Das Skript legt die Höhe des Blocks fest (finalHeight), wonach der Benutzer Geld vom Konto abheben kann.
heightUnit - Die Anzahl der Blöcke in einer Zeiteinheit (z. B. Monat, Jahr usw.). Zuerst suchen wir nach einem Eintrag mit einem Paar (Schlüssel, Wert) = (initialTransferTransaction, futureDataTransaction). Anschließend muss der Benutzer TransferTransaction mit den korrekten Informationen über den Betrag der Einzahlung und die für den Zeitraum der Einzahlung aufgelaufenen Zinsen senden. Diese Informationen werden mit der ursprünglichen TransferTransaction verglichen, die im aktuellen TransferTransaction-Proof enthalten ist. DepositDivisor ist die Zahl, die umgekehrt zum Anteil der Einzahlung ist (wenn die Einzahlung mit 10% akzeptiert wird, beträgt der Anteil der Einzahlung 0,1 und 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) }
Im dritten und letzten Artikel dieser Reihe werden wir uns mit weiteren Optionen für die Verwendung intelligenter Assets befassen, einschließlich des Einfrierens und Einschränkens von Transaktionen für bestimmte Adressen.