Wir lernen, Wave-Smart Contracts auf RIDE und RIDE4DAPPS zu schreiben. Teil 2 (DAO – Dezentrale Autonome Organisation)

Wir lernen, Wave-Smart Contracts auf RIDE und RIDE4DAPPS zu schreiben. Teil 2 (DAO – Dezentrale Autonome Organisation)

Hallo zusammen!

In zuerst Teil haben wir im Detail besprochen, wie man dApps (dezentralisierte Anwendungen) in Waves RIDE IDE.

Lassen Sie uns nun etwas testen, was wir durchgegangen sind. Nummer 00 oder.

Schritt 3. Testen des dApp-Kontos

Wir lernen, Wave-Smart Contracts auf RIDE und RIDE4DAPPS zu schreiben. Teil 2 (DAO – Dezentrale Autonome Organisation)

Welche Probleme fallen sofort auf, wenn wir Alice dApp Konto betrachten?
ZunÀchst:
Boob und Cooper könnten versehentlich Mittel an die dApp-Adresse mit einer normalen Überweisung senden und hĂ€tten somit keinen Zugang zu diesen Mitteln.

Zweitens:
Wir beschrĂ€nken Alice nicht darin, Mittel ohne Zustimmung von Boob oder Cooper abzuheben. Beachten Sie, dass alle Transaktionen von Alice sofort ausgefĂŒhrt werden.

Lassen Sie uns das Zweite beheben, indem wir Alice Überweisung die Transaktionen verbieten. Wir deployen das korrigierte Skript:
Wir lernen, Wave-Smart Contracts auf RIDE und RIDE4DAPPS zu schreiben. Teil 2 (DAO – Dezentrale Autonome Organisation)
ïżŒ
Wir versuchen, Coins von dApp Alice mit ihrer Signatur abzuheben. Wir erhalten einen Fehler:
Wir lernen, Wave-Smart Contracts auf RIDE und RIDE4DAPPS zu schreiben. Teil 2 (DAO – Dezentrale Autonome Organisation)

Wir versuchen es ĂŒber den Abzug:

broadcast(invokeScript({dappAddress: address(env.accounts[1]), call:{function:"withdraw",args:[{type:"integer", value: 1000000}]}, payment: []}))

Das Skript funktioniert und wir haben Punkt 2 geklÀrt!

Schritt 4. Erstellen eines DAO mit Abstimmung

Leider bietet die RIDE-Sprache derzeit keine Möglichkeiten zur Arbeit mit Sammlungen (WörterbĂŒcher von WörterbĂŒchern, Iteratoren, Reduzierer usw.). FĂŒr alle Operationen mit flachen Sammlungen SchlĂŒssel-Wert Wir können ein System zur Arbeit mit Strings entwerfen, einschließlich der SchlĂŒssel und deren Dekodierung.

Strings lassen sich sehr einfach verketten, und sie können an Indizes aufgeteilt werden.
Lass uns ein Beispiel nehmen, um einen String zusammenzustellen und zu analysieren und zu prĂŒfen, wie sich das auf den Transaktionsausgang auswirkt.
Wir haben festgestellt, dass Alice die Transfertransaktion nicht unterzeichnen konnte, da diese Möglichkeit im @verifier fĂŒr diesen Transaktionstyp blockiert war.

Lass uns ein bisschen mit Strings ĂŒben und das Problem dann lösen.

RIDE Strings

Die Transaktion ist wieder möglich, wir können mit Strings arbeiten.
Wir lernen, Wave-Smart Contracts auf RIDE und RIDE4DAPPS zu schreiben. Teil 2 (DAO – Dezentrale Autonome Organisation)

ïżŒ
Zusammenfassend haben wir alles, was wir fĂŒr die Erstellung komplexer Logik benötigen. DAO dApp.

Datentransaktionen

Datentransaktionen:
„Die maximale GrĂ¶ĂŸe fĂŒr einen SchlĂŒssel betrĂ€gt 100 Zeichen, und ein SchlĂŒssel kann beliebige Unicode-Codepunkte einschließlich Leerzeichen und anderer nicht druckbarer Symbole enthalten. String-Werte haben eine Begrenzung von 32.768 Bytes und die maximale Anzahl möglicher EintrĂ€ge in einer Daten Transaktion betrĂ€gt 100. Insgesamt betrĂ€gt die maximale GrĂ¶ĂŸe einer Daten Transaktion etwa 140 KB — vergleichbar mit der LĂ€nge von Shakespeares StĂŒck 'Romeo und Julia'.“

Erstellen Sie ein DAO unter den folgenden Bedingungen:
Damit ein Startup Finanzierung erhalten kann, muss getFunds() mindestens 2 Teilnehmer - DAO-Investoren - unterstĂŒtzen. Ausgeben Es wird genau so viel möglich sein, wie insgesamt angegeben auf der Abstimmung der DAO-EigentĂŒmer.

Lassen Sie uns 3 Arten von SchlĂŒsseln erstellen und die Logik fĂŒr die Arbeit mit den Bilanzen in zwei neuen Funktionen vote und getFunds hinzufĂŒgen:
xx
xx_ia = Investoren, verfĂŒgbarer Balance (vote, deposit, withdrawal)
xx
xx_sv = Startups, Anzahl der Stimmen (vote, getFunds)
xx
xx_sf = Startups, Anzahl der Stimmen (vote, getFunds)
xx
xx = öffentliche Adresse (35 Zeichen)

Beachten Sie, dass wir in Vote mehrere Felder gleichzeitig aktualisieren mussten:

WriteSet([DataEntry(key1, value1), DataEntry(key2, value2)]),

WriteSet ermöglicht es uns, mehrere EintrÀge in einem einzigen invokeScript Transaktion zu machen.

So sieht es im key-value Speicher des DAO dApp aus, nachdem Bob und Cooper ia- Einzahlungen:
Wir lernen, Wave-Smart Contracts auf RIDE und RIDE4DAPPS zu schreiben. Teil 2 (DAO – Dezentrale Autonome Organisation)

Die Einzahlungsfunktion hat sich leicht geÀndert:
Wir lernen, Wave-Smart Contracts auf RIDE und RIDE4DAPPS zu schreiben. Teil 2 (DAO – Dezentrale Autonome Organisation)

Jetzt kommt der entscheidende Moment in der TĂ€tigkeit der DAO — die Abstimmung ĂŒber Projekte zur Finanzierung.

Bob stimmt fĂŒr das Projekt Neli mit 500000 Wavelets:

broadcast(invokeScript({dappAddress: address(env.accounts[1]), call:{function:"vote",args:[{type:"integer", value: 500000}, {type:"string", value: "3MrXEKJr9nDLNyVZ1d12Mq4jjeUYwxNjMsH"}]}, payment: []}))

Wir lernen, Wave-Smart Contracts auf RIDE und RIDE4DAPPS zu schreiben. Teil 2 (DAO – Dezentrale Autonome Organisation)

Im Datenspeicher sehen wir alle erforderlichen EintrĂ€ge fĂŒr die Adresse Neli:
Wir lernen, Wave-Smart Contracts auf RIDE und RIDE4DAPPS zu schreiben. Teil 2 (DAO – Dezentrale Autonome Organisation)
Cooper hat ebenfalls fĂŒr das Projekt Neli gestimmt.
Wir lernen, Wave-Smart Contracts auf RIDE und RIDE4DAPPS zu schreiben. Teil 2 (DAO – Dezentrale Autonome Organisation)

Lassen Sie uns den Code der Funktion ansehen getFunds. Neli muss mindestens 2 Stimmen sammeln, um Gelder aus dem DAO abheben zu können.
Wir lernen, Wave-Smart Contracts auf RIDE und RIDE4DAPPS zu schreiben. Teil 2 (DAO – Dezentrale Autonome Organisation)

Neli plant, die HĂ€lfte des ihr anvertrauten Betrags abzuheben:

broadcast(invokeScript({dappAddress: address(env.accounts[1]), call:{function:"getFunds",args:[{type:"integer", value: 500000}]}, payment: []}))

Wir lernen, Wave-Smart Contracts auf RIDE und RIDE4DAPPS zu schreiben. Teil 2 (DAO – Dezentrale Autonome Organisation)

Das gelingt ihr, was beweist, dass das DAO funktioniert!

Wir haben den Prozess zur Erstellung eines DAO in der Sprache betrachtet RIDE4DAPPS.
In den nÀchsten Teilen werden wir uns eingehender mit der Refaktorisierung des Codes und der Testung der FÀlle beschÀftigen.

Die vollstÀndige Version des Codes befindet sich in Waves RIDE IDE:

# In this example multiple accounts can deposit their funds to DAO and safely take them back, no one can interfere with this.
# DAO participants can also vote for particular addresses and let them withdraw invested funds then quorum has reached.
# An inner state is maintained as mapping `address=>waves`.
# https://medium.com/waves-lab/waves-announces-funding-for-ride-for-dapps-developers-f724095fdbe1

# You can try this contract by following commands in the IDE (ide.wavesplatform.com)
# Run commands as listed below
# From account #0:
#      deploy()
# From account #1: deposit funds
#      broadcast(invokeScript({dappAddress: address(env.accounts[1]), call:{function:"deposit",args:[]}, payment: [{amount: 100000000, asset:null }]}))
# From account #2: deposit funds
#      broadcast(invokeScript({dappAddress: address(env.accounts[1]), call:{function:"deposit",args:[]}, payment: [{amount: 100000000, asset:null }]}))
# From account #1: vote for startup
#      broadcast(invokeScript({dappAddress: address(env.accounts[1]), call:{function:"vote",args:[{type:"integer", value: 500000}, {type:"string", value: "3MrXEKJr9nDLNyVZ1d12Mq4jjeUYwxNjMsH"}]}, payment: []}))
# From account #2: vote for startup
#      broadcast(invokeScript({dappAddress: address(env.accounts[1]), call:{function:"vote",args:[{type:"integer", value: 500000}, {type:"string", value: "3MrXEKJr9nDLNyVZ1d12Mq4jjeUYwxNjMsH"}]}, payment: []}))
# From account #3: get invested funds
#      broadcast(invokeScript({dappAddress: address(env.accounts[1]), call:{function:"getFunds",args:[{type:"integer", value: 500000}]}, payment: []}))

{-# STDLIB_VERSION 3 #-}
{-# CONTENT_TYPE DAPP #-}
{-# SCRIPT_TYPE ACCOUNT #-}

@Callable(i)
func deposit() = {
   let pmt = extract(i.payment)
   if (isDefined(pmt.assetId)) then throw("can hodl waves only at the moment")
   else {
        let currentKey = toBase58String(i.caller.bytes)
        let xxxInvestorBalance = currentKey + "_" + "ib"
        let currentAmount = match getInteger(this, xxxInvestorBalance) {
            case a:Int => a
            case _ => 0
        }
        let newAmount = currentAmount + pmt.amount
        WriteSet([DataEntry(xxxInvestorBalance, newAmount)])
   }
}
@Callable(i)
func withdraw(amount: Int) = {
        let currentKey = toBase58String(i.caller.bytes)
        let xxxInvestorBalance = currentKey + "_" + "ib"
        let currentAmount = match getInteger(this, xxxInvestorBalance) {
            case a:Int => a
            case _ => 0
        }
        let newAmount = currentAmount - amount
     if (amount < 0)
            then throw("Can't withdraw negative amount")
    else if (newAmount < 0)
            then throw("Not enough balance")
            else ScriptResult(
                    WriteSet([DataEntry(xxxInvestorBalance, newAmount)]),
                    TransferSet([ScriptTransfer(i.caller, amount, unit)])
                )
    }
@Callable(i)
func getFunds(amount: Int) = {
        let quorum = 2
        let currentKey = toBase58String(i.caller.bytes)
        let xxxStartupFund = currentKey + "_" + "sf"
        let xxxStartupVotes = currentKey + "_" + "sv"
        let currentAmount = match getInteger(this, xxxStartupFund) {
            case a:Int => a
            case _ => 0
        }
        let totalVotes = match getInteger(this, xxxStartupVotes) {
            case a:Int => a
            case _ => 0
        }
        let newAmount = currentAmount - amount
    if (amount < 0)
            then throw("Can't withdraw negative amount")
    else if (newAmount < 0)
            then throw("Not enough balance")
    else if (totalVotes < quorum)
            then throw("Not enough votes. At least 2 votes required!")
    else ScriptResult(
                    WriteSet([
                        DataEntry(xxxStartupFund, newAmount)
                        ]),
                    TransferSet([ScriptTransfer(i.caller, amount, unit)])
                )
    }
@Callable(i)
func vote(amount: Int, address: String) = {
        let currentKey = toBase58String(i.caller.bytes)
        let xxxInvestorBalance = currentKey + "_" + "ib"
        let xxxStartupFund = address + "_" + "sf"
        let xxxStartupVotes = address + "_" + "sv"
        let currentAmount = match getInteger(this, xxxInvestorBalance) {
            case a:Int => a
            case _ => 0
        }
        let currentVotes = match getInteger(this, xxxStartupVotes) {
            case a:Int => a
            case _ => 0
        }
        let currentFund = match getInteger(this, xxxStartupFund) {
            case a:Int => a
            case _ => 0
        }
    if (amount <= 0)
            then throw("Can't withdraw negative amount")
    else if (amount > currentAmount)
            then throw("Not enough balance")
    else ScriptResult(
                    WriteSet([
                        DataEntry(xxxInvestorBalance, currentAmount - amount),
                        DataEntry(xxxStartupVotes, currentVotes + 1),
                        DataEntry(xxxStartupFund, currentFund + amount)
                        ]),
                    TransferSet([ScriptTransfer(i.caller, amount, unit)])
            )
    }
@Verifier(tx)
func verify() = {
    match tx {
        case t: TransferTransaction =>false
        case _ => true
    }
}

Erster Teil
Der Code auf GitHub
Waves RIDE IDE
AnkĂŒndigung des Förderprogramms

Quelle: habr.com

Kaufen Sie zuverlĂ€ssiges Hosting fĂŒr Websites mit DDoS-Schutz, VPS VDS-Server đŸ”„ Kaufen Sie zuverlĂ€ssiges Hosting fĂŒr Websites mit DDoS-Schutz, VPS VDS-Server | ProHoster