Mācīšanās rakstīt Waves viedos līgumus RIDE un RIDE4DAPPS. 2. daļa (DAO — decentralizēta autonoma organizācija)

Mācīšanās rakstīt Waves viedos līgumus RIDE un RIDE4DAPPS. 2. daļa (DAO — decentralizēta autonoma organizācija)

Sveiki visiem!

В pirmais daļā mēs detalizēti apskatījām, kā izveidot un strādāt ar dApp (decentralizētu lietojumprogrammu). Waves RIDE IDE.

Tagad nedaudz pārbaudīsim izjaukto piemērs.

3. posms. dApp konta pārbaude

Mācīšanās rakstīt Waves viedos līgumus RIDE un RIDE4DAPPS. 2. daļa (DAO — decentralizēta autonoma organizācija)

Kādas problēmas jums uzreiz uznāk ar Alisi? dApp Konts?
Pirmkārt:
Būs un Kūpers var nejauši nosūtīt līdzekļus uz dApp adresi, izmantojot parasto pārsūtīt darījumiem un tādējādi nevarēs tiem piekļūt atpakaļ.

Otrkārt:
Mēs nekādā veidā neierobežojam Alises iespēju izņemt līdzekļus bez Boob un/vai Kūpera piekrišanas. Tā kā, pievērsiet uzmanību pārbaudei, visi darījumi no Alises tiks izpildīti.

Labosim 2., aizliedzot Alisi pārsūtīt darījumiem. Izvietosim laboto skriptu:
Mācīšanās rakstīt Waves viedos līgumus RIDE un RIDE4DAPPS. 2. daļa (DAO — decentralizēta autonoma organizācija)

Mēs cenšamies izņemt monētas no dApp Alises un viņas paraksta. Mēs saņemam kļūdu:
Mācīšanās rakstīt Waves viedos līgumus RIDE un RIDE4DAPPS. 2. daļa (DAO — decentralizēta autonoma organizācija)

Mēģināsim izņemt, izmantojot izņemšanu:

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

Scenārijs strādā, un mēs izdomājām 2. punktu!

4. posms. Izveidojiet DAO ar balsošanu

Diemžēl RIDE valoda vēl nenodrošina iespēju strādāt ar kolekcijām (vārdnīcu vārdnīcām, iteratoriem, reducētājiem utt.). Tomēr jebkurai darbībai ar plakanām kolekcijām atslēgas vērtība varam izstrādāt sistēmu darbam ar virknēm, attiecīgi ar atslēgām un to atšifrēšanu.

Virknes ir ļoti viegli savienot; virknes var atdalīt ar indeksiem.
Apkoposim un parsēsim virkni kā testa piemēru un pārbaudīsim, kā tas ietekmē darījuma iznākumu.
Mēs samierinājāmies ar faktu, ka Alise nevarēja parakstīt pārsūtīšanas darījumu, jo šī iespēja tika bloķēta @verifier šāda veida darījumam.

Praktizēsimies ar stīgām un pēc tam atrisināsim to.

RIDE Stīgas

Darījums atkal ir iespējams, mēs protam strādāt ar stīgām.
Mācīšanās rakstīt Waves viedos līgumus RIDE un RIDE4DAPPS. 2. daļa (DAO — decentralizēta autonoma organizācija)


Kopumā mums ir viss nepieciešamais sarežģītas loģikas rakstīšanai DAO dApp.

Datu transakcijas

Datu darījumi:
“Maksimālais atslēgas izmērs ir 100 rakstzīmes, un atslēgā var būt patvaļīgi unikoda koda punkti, tostarp atstarpes un citi nedrukājami simboli. Virkņu vērtību ierobežojums ir 32,768 100 baiti, un maksimālais iespējamo ierakstu skaits datu transakcijā ir 140. Kopumā maksimālais datu transakcijas lielums ir aptuveni XNUMX kb — atsaucei gandrīz precīzi Šekspīra lugas “Romeo un Džuljeta” garums. '.”

Mēs izveidojam DAO ar šādiem nosacījumiem:
Lai jaunuzņēmums saņemtu finansējumu, zvanot pa tālr getFunds () nepieciešams vismaz 2 dalībnieku - DAO investoru - atbalsts. Izeja tas būs iespējams tieši tik, cik kopā norādīts balsošana DAO īpašnieki.

Izgatavosim 3 veidu atslēgas un pievienosim loģiku darbam ar atlikumiem 2 jaunās funkcijās balsošana un saņemšana:
xx…xx_ia = investori, pieejamais atlikums (balsošana, depozīts, izņemšana)
xx…xx_sv = starta uzņēmumi, balsu skaits (balsot, saņemt līdzekļus)
xx…xx_sf = starta uzņēmumi, balsu skaits (balsot, saņemt līdzekļus)
xx…xx = publiskā adrese (35 rakstzīmes)

Lūdzu, ņemiet vērā, ka balsojumā mums bija jāatjaunina vairāki lauki vienlaikus:

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

WriteSet ļauj mums vienā reizē veikt vairākus ierakstus invokeScript darījumiem.

Šādi tas izskatās DAO dApp atslēgu vērtību krātuvē pēc tam, kad Bobs un Kūpers ir papildinājuši ia- noguldījumi:
Mācīšanās rakstīt Waves viedos līgumus RIDE un RIDE4DAPPS. 2. daļa (DAO — decentralizēta autonoma organizācija)

Mūsu depozīta funkcija ir nedaudz mainījusies:
Mācīšanās rakstīt Waves viedos līgumus RIDE un RIDE4DAPPS. 2. daļa (DAO — decentralizēta autonoma organizācija)

Tagad ir pienācis vissvarīgākais brīdis DAO darbībā - balsojums finansējamiem projektiem.

Bobs balso par Nelijas 500000 XNUMX viļņu projektu:

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

Mācīšanās rakstīt Waves viedos līgumus RIDE un RIDE4DAPPS. 2. daļa (DAO — decentralizēta autonoma organizācija)

Datu krātuvē redzam visus nepieciešamos ierakstus Nelija adresei:
Mācīšanās rakstīt Waves viedos līgumus RIDE un RIDE4DAPPS. 2. daļa (DAO — decentralizēta autonoma organizācija)
Kūpers arī balsoja par Neli projektu.
Mācīšanās rakstīt Waves viedos līgumus RIDE un RIDE4DAPPS. 2. daļa (DAO — decentralizēta autonoma organizācija)

Apskatīsim funkcijas kodu saņemtFunds. Neli ir jāsavāc vismaz 2 balsis, lai varētu izņemt līdzekļus no DAO.
Mācīšanās rakstīt Waves viedos līgumus RIDE un RIDE4DAPPS. 2. daļa (DAO — decentralizēta autonoma organizācija)

Neli gatavojas izņemt pusi no viņai uzticētās summas:

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

Mācīšanās rakstīt Waves viedos līgumus RIDE un RIDE4DAPPS. 2. daļa (DAO — decentralizēta autonoma organizācija)

Viņai tas izdodas, tas ir, DAO strādā!

Mēs apskatījām DAO izveides procesu valodā RIDE4DAPPS.
Nākamajās daļās mēs sīkāk aplūkosim koda pārveidošanu un gadījumu testēšanu.

Pilna koda versija iekšā 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
    }
}

Pirmā daļa
Kods vietnē GitHub
Waves RIDE IDE
Grantu programmas izsludināšana

Avots: www.habr.com

Pievieno komentāru