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

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

Hallo zusammen!

Im erste Teil haben wir ausfĂŒhrlich betrachtet, wie man dApp (dezentralisierte Anwendung) in Waves RIDE IDE.

Lass uns jetzt ein wenig den analysierten Beispiel.

Schritt 3. Testen des dApp-Kontos

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

Welche Probleme fallen sofort bei Alice ins Auge? dApp Konto?
Erstens:
Boob und Cooper könnten versehentlich Geld an die dApp-Adresse mit einer normalen transfer Transaktion senden und hÀtten somit keinen Zugriff darauf.

Zweitens:
Wir schrĂ€nken Alice in der Abhebung von Geldern nicht ein, ohne RĂŒcksprache mit Boob oder Cooper. Beachte, dass alle Transaktionen von Alice ausgefĂŒhrt werden.

Lass uns den zweiten Punkt korrigieren, indem wir Alice transfer Transaktionen verbieten. Wir deployen das korrigierte Skript:
Wir lernen, Waves Smart Contracts auf RIDE und RIDE4DAPPS zu schreiben. Teil 2 (DAO - Dezentrale Autonome Organisation)
ïżŒ
Wir versuchen, MĂŒnzen mit Alice und ihrer Unterschrift von der dApp abzuheben. Wir erhalten einen Fehler:
Wir lernen, Waves Smart Contracts auf RIDE und RIDE4DAPPS zu schreiben. Teil 2 (DAO - Dezentrale Autonome Organisation)

Wir versuchen es mit withdraw:

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

Das Skript funktioniert und wir haben den zweiten Punkt geklÀrt!

Schritt 4. Erstellen einer DAO mit Abstimmung

Leider bietet die Sprache RIDE bisher keine Möglichkeiten zur Arbeit mit Sammlungen (Wörterbuch von WörterbĂŒchern, Iteratoren, Reducer usw.). FĂŒr alle Operationen mit flachen Sammlungen key-value können wir jedoch ein System zur Arbeit mit Zeichenfolgen entwerfen, entsprechend mit SchlĂŒsseln und deren EntschlĂŒsselung.

Zeichenfolgen können sehr einfach verkettet werden, sie können nach Indizes aufgeteilt werden.
Lass uns als Testbeispiel eine Zeichenfolge zusammenstellen und analysieren und ĂŒberprĂŒfen, wie sich das auf das Ergebnis der Transaktion auswirkt.
Wir sind dabei, dass Alice die Transfer-Transaktion nicht unterzeichnen konnte, da diese Möglichkeit im @verifier fĂŒr diesen Transaktionstyp blockiert war.

Lass uns mit Zeichenfolgen ĂŒben und dann dies erlauben.

RIDE Zeichenfolgen

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

ïżŒ
Zusammengefasst haben wir alles Notwendige fĂŒr das Schreiben komplexer Logik DAO dApp.

Daten-Transaktionen

Daten-Transaktionen:
„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 Grenze 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 - zum Vergleich, fast genau die LĂ€nge von Shakespeares StĂŒck ‚Rom und Julia‘.“

Wir erstellen eine DAO unter folgenden Bedingungen:
Um Finanzierung fĂŒr ein Start-up zu erhalten, indem wir getFunds() aufrufen, ist die UnterstĂŒtzung von mindestens 2 Teilnehmern - DAO-Investoren erforderlich. Ausgabe Es wird genau so viel möglich sein, wie insgesamt beim Abstimmung von den DAO-EigentĂŒmern angegeben wurde.

Lassen Sie uns 3 Arten von SchlĂŒsseln erstellen und eine Logik fĂŒr den Umgang mit Bilanzen in 2 neuen Funktionen vote und getFunds hinzufĂŒgen:
xx
xx_ia = Investoren, verfĂŒgbarer Betrag (vote, deposit, withdrawal)
xx
xx_sv = Startups, Anzahl der Stimmen (vote, getFunds)
xx
xx_sf = Startups, Anzahl der Stimmen (vote, getFunds)
xx
xx = öffentlicher SchlĂŒssel (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 innerhalb eines invokeScript Transaktionsrahmens zu erstellen.

So sieht es im key-value Speicher der DAO dApp aus, nachdem Bob und Cooper aufgefĂŒllt haben ia- Einlagen:
Wir lernen, Waves Smart Contracts auf RIDE und RIDE4DAPPS zu schreiben. Teil 2 (DAO - Dezentrale Autonome Organisation)

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

Jetzt kommt der wichtigste Moment in der TĂ€tigkeit der DAO — die Abstimmung fĂŒr Projekte zur Finanzierung.

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

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

Wir lernen, Waves 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, Waves 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, Waves Smart Contracts auf RIDE und RIDE4DAPPS zu schreiben. Teil 2 (DAO - Dezentrale Autonome Organisation)

Lassen Sie uns den Code der Funktion anschauen getFunds. Neli muss mindestens 2 Stimmen sammeln, um Geld aus der DAO abheben zu können.
Wir lernen, Waves 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, Waves Smart Contracts auf RIDE und RIDE4DAPPS zu schreiben. Teil 2 (DAO - Dezentrale Autonome Organisation)

Das gelingt ihr, das heißt, die DAO funktioniert!

Wir haben den Prozess der Erstellung einer DAO in der Sprache RIDE4DAPPS.
In den nÀchsten Teilen werden wir uns nÀher mit der Code-Umstrukturierung und den TestfÀllen befassen.

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
Code auf GitHub
Waves RIDE IDE
AnkĂŒndigung des Stipendienprogramms

Quelle: habr.com

ZuverlĂ€ssiges Hosting fĂŒr Websites mit DDoS-Schutz kaufen, VPS VDS Server đŸ”„ ZuverlĂ€ssiges Hosting fĂŒr Websites mit DDoS-Schutz kaufen, VPS VDS Server - ProHoster