Μάθετε πώς να γράφετε έξυπνα συμβόλαια Waves στο RIDE και στο RIDE4DAPPS. Μέρος 2 (DAO - Αποκεντρωμένη Αυτόνομη Οργάνωση)

Μάθετε πώς να γράφετε έξυπνα συμβόλαια Waves στο RIDE και στο RIDE4DAPPS. Μέρος 2 (DAO - Αποκεντρωμένη Αυτόνομη Οργάνωση)

Γεια σε όλους!

В πρώτος μέρος, έχουμε εξετάσει λεπτομερώς πώς να δημιουργήσετε και να εργαστείτε με μια dApp (αποκεντρωμένη εφαρμογή) σε Waves RIDE IDE.

Ας δοκιμάσουμε τώρα λίγο το αποσυναρμολογημένο παράδειγμα.

Στάδιο 3. Δοκιμή του λογαριασμού dApp

Μάθετε πώς να γράφετε έξυπνα συμβόλαια Waves στο RIDE και στο RIDE4DAPPS. Μέρος 2 (DAO - Αποκεντρωμένη Αυτόνομη Οργάνωση)

Τι προβλήματα βιάζονται αμέσως στις φωνές με την Αλίκη dApp Λογαριασμός?
Πρώτον:
Ο Boob και ο Cooper ενδέχεται να στείλουν κατά λάθος χρήματα σε μια διεύθυνση dApp χρησιμοποιώντας μια κανονική διεύθυνση μεταφορά συναλλαγές και επομένως δεν θα είναι δυνατή η πρόσβαση σε αυτές.

Δεύτερον:
Δεν περιορίζουμε με κανέναν τρόπο την Alice από την ανάληψη κεφαλαίων χωρίς τη συγκατάθεση του Boob ή/και του Cooper. Επειδή, δώστε προσοχή στην επαλήθευση, όλες οι συναλλαγές από την Alice θα εκτελεστούν.

Ας διορθώσουμε το 2 αποκλείοντας την Αλίκη μεταφορά συναλλαγές. Αναπτύξτε το διορθωμένο σενάριο:
Μάθετε πώς να γράφετε έξυπνα συμβόλαια Waves στο RIDE και στο RIDE4DAPPS. Μέρος 2 (DAO - Αποκεντρωμένη Αυτόνομη Οργάνωση)

Προσπαθούμε να αποσύρουμε νομίσματα με την dApp Alice και την υπογραφή της. Λαμβάνουμε ένα σφάλμα:
Μάθετε πώς να γράφετε έξυπνα συμβόλαια Waves στο RIDE και στο RIDE4DAPPS. Μέρος 2 (DAO - Αποκεντρωμένη Αυτόνομη Οργάνωση)

Προσπάθεια ανάληψης μέσω ανάληψης:

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

Το σενάριο λειτουργεί και καταλάβαμε το 2ο σημείο!

Στάδιο 4. Δημιουργήστε ένα DAO με ψηφοφορία

Δυστυχώς, η γλώσσα RIDE δεν παρέχει ακόμη τη δυνατότητα εργασίας με συλλογές (λεξικά, λεξικά, επαναλήπτες, μειωτήρες κ.λπ.). Ωστόσο, για τυχόν εργασίες σε επίπεδες συλλογές κλειδί-τιμή μπορούμε να σχεδιάσουμε ένα σύστημα για εργασία με χορδές, αντίστοιχα με κλειδιά και την αποκρυπτογράφηση τους.

Οι συμβολοσειρές είναι πολύ εύκολο να συνδεθούν, οι συμβολοσειρές μπορούν να διαχωριστούν με ευρετήρια.
Ας συλλέξουμε και αναλύσουμε τη συμβολοσειρά ως δοκιμαστική περίπτωση και ας ελέγξουμε πώς αυτό θα επηρεάσει το αποτέλεσμα της συναλλαγής.
Καταλήξαμε στο γεγονός ότι η Alice δεν μπορούσε να υπογράψει τη συναλλαγή μεταφοράς, καθώς αυτή η δυνατότητα ήταν αποκλεισμένη στο @verifier για αυτόν τον τύπο συναλλαγής.

Ας εξασκηθούμε με χορδές και μετά λύνουμε αυτό.

RIDE Strings

Η συναλλαγή είναι ξανά δυνατή, ξέρουμε πώς να δουλεύουμε με συμβολοσειρές.
Μάθετε πώς να γράφετε έξυπνα συμβόλαια Waves στο RIDE και στο RIDE4DAPPS. Μέρος 2 (DAO - Αποκεντρωμένη Αυτόνομη Οργάνωση)


Συνολικά, έχουμε όλα όσα χρειάζεστε για να γράψετε πολύπλοκη λογική DAO dApp.

Συναλλαγές δεδομένων

Συναλλαγές δεδομένων:
"Το μέγιστο μέγεθος για ένα κλειδί είναι 100 χαρακτήρες και ένα κλειδί μπορεί να περιέχει αυθαίρετα σημεία κωδικού Unicode, συμπεριλαμβανομένων κενών και άλλων μη εκτυπώσιμων συμβόλων. Οι τιμές συμβολοσειρών έχουν όριο 32,768 byte και ο μέγιστος αριθμός πιθανών καταχωρήσεων στη συναλλαγή δεδομένων είναι 100. Συνολικά, το μέγιστο μέγεθος μιας συναλλαγής δεδομένων είναι περίπου 140 kb — για αναφορά, σχεδόν ακριβώς το μήκος του έργου του Σαίξπηρ «Ρωμαίος και Ιουλιέτα ''.

Δημιουργούμε ένα DAO με τις ακόλουθες προϋποθέσεις:
Για να πάρει χρηματοδότηση μια startup τηλεφωνώντας getFunds() απαιτείται η υποστήριξη τουλάχιστον 2 συμμετεχόντων - επενδυτές DAO. Έξοδος θα είναι δυνατό ακριβώς όσο το ποσό που αναφέρεται ψηφοφορία Ιδιοκτήτες DAO.

Ας φτιάξουμε 3 τύπους κλειδιών και ας προσθέσουμε λογική για εργασία με υπόλοιπα σε 2 νέες συναρτήσεις vote και getFunds:
xx…xx_ia = επενδυτές, διαθέσιμο υπόλοιπο (ψηφοφορία, κατάθεση, ανάληψη)
xx…xx_sv = startups, αριθμός ψήφων (ψηφοφορία, λάβετε κεφάλαια)
xx…xx_sf = startups, αριθμός ψήφων (ψηφοφορία, λάβετε κεφάλαια)
xx…xx = δημόσια διεύθυνση (35 χαρακτήρες)

Σημείωση στο Vote χρειαζόταν να ενημερώσουμε πολλά πεδία ταυτόχρονα:

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

Το WriteSet μας επιτρέπει να κάνουμε πολλές εγγραφές ταυτόχρονα σε μία invokeScript συναλλαγές.

Έτσι φαίνεται στο κατάστημα κλειδιών αξίας του DAO dApp μετά την αναπλήρωση του Bob και του Cooper ia- καταθέσεις:
Μάθετε πώς να γράφετε έξυπνα συμβόλαια Waves στο RIDE και στο RIDE4DAPPS. Μέρος 2 (DAO - Αποκεντρωμένη Αυτόνομη Οργάνωση)

Η λειτουργία κατάθεσης έχει αλλάξει ελαφρώς:
Μάθετε πώς να γράφετε έξυπνα συμβόλαια Waves στο RIDE και στο RIDE4DAPPS. Μέρος 2 (DAO - Αποκεντρωμένη Αυτόνομη Οργάνωση)

Τώρα έρχεται η πιο σημαντική στιγμή στις δραστηριότητες του DAO - ψήφος για έργα προς χρηματοδότηση.

Ο Bob ψηφίζει για το έργο Neli σε 500000 wavelet:

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

Μάθετε πώς να γράφετε έξυπνα συμβόλαια Waves στο RIDE και στο RIDE4DAPPS. Μέρος 2 (DAO - Αποκεντρωμένη Αυτόνομη Οργάνωση)

Στο χώρο αποθήκευσης δεδομένων, βλέπουμε όλες τις απαραίτητες καταχωρήσεις για τη διεύθυνση Neli:
Μάθετε πώς να γράφετε έξυπνα συμβόλαια Waves στο RIDE και στο RIDE4DAPPS. Μέρος 2 (DAO - Αποκεντρωμένη Αυτόνομη Οργάνωση)
Ο Κούπερ ψήφισε επίσης υπέρ του έργου Neli.
Μάθετε πώς να γράφετε έξυπνα συμβόλαια Waves στο RIDE και στο RIDE4DAPPS. Μέρος 2 (DAO - Αποκεντρωμένη Αυτόνομη Οργάνωση)

Ας ρίξουμε μια ματιά στον κωδικό λειτουργίας getFunds. Η Neli πρέπει να συγκεντρώσει τουλάχιστον 2 ψήφους για να μπορέσει να αποσύρει χρήματα από το DAO.
Μάθετε πώς να γράφετε έξυπνα συμβόλαια Waves στο RIDE και στο RIDE4DAPPS. Μέρος 2 (DAO - Αποκεντρωμένη Αυτόνομη Οργάνωση)

Η Νέλη πρόκειται να αποσύρει το μισό από το ποσό που της εμπιστεύτηκε:

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

Μάθετε πώς να γράφετε έξυπνα συμβόλαια Waves στο RIDE και στο RIDE4DAPPS. Μέρος 2 (DAO - Αποκεντρωμένη Αυτόνομη Οργάνωση)

Τα καταφέρνει, δηλαδή δουλεύει το DAO!

Εξετάσαμε τη διαδικασία δημιουργίας DAO στη γλώσσα RIDE4DAPPS.
Στα επόμενα μέρη, θα ρίξουμε μια πιο προσεκτική ματιά στην αναδιαμόρφωση κώδικα και τη δοκιμή περιπτώσεων.

Πλήρης κωδικός μέσα 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
    }
}

Το πρώτο μέρος
Κωδικός στο github
Waves RIDE IDE
Ανακοίνωση Προγράμματος Επιχορήγησης

Πηγή: www.habr.com

Προσθέστε ένα σχόλιο