Learje om Waves smart kontrakten te skriuwen op RIDE en RIDE4DAPPS. Diel 2 (DAO - Desintralisearre autonome organisaasje)

Learje om Waves smart kontrakten te skriuwen op RIDE en RIDE4DAPPS. Diel 2 (DAO - Desintralisearre autonome organisaasje)

Hello everyone!

В de earste diel wy seagen yn detail hoe te meitsjen en wurkje mei dApp (desintralisearre applikaasje) yn Waves RIDE IDE.

Litte wy de útinoarte no in bytsje testje foarbyld.

Stage 3. It testen fan it dApp-akkount

Learje om Waves smart kontrakten te skriuwen op RIDE en RIDE4DAPPS. Diel 2 (DAO - Desintralisearre autonome organisaasje)

Hokker problemen springe jo fuortendaliks út mei Alice? dApp Rekken?
Earst:
Boob en Cooper meie per ongeluk fûnsen stjoere nei it dApp-adres mei gewoane oerdracht transaksjes en dus net by steat wêze om tagong ta harren werom.

Twad:
Wy beheine Alice net op ien of oare manier fan it weromlûken fan fûnsen sûnder de goedkarring fan Boob en / of Cooper. Sûnt, betelje omtinken foar ferifiearjen, sille alle transaksjes fan Alice wurde útfierd.

Litte wy 2e reparearje troch Alice te ferbieden oerdracht transaksjes. Litte wy it korrizjearre skript ynsette:
Learje om Waves smart kontrakten te skriuwen op RIDE en RIDE4DAPPS. Diel 2 (DAO - Desintralisearre autonome organisaasje)

Wy besykje munten werom te lûken fan dApp Alice en har hantekening. Wy krije in flater:
Learje om Waves smart kontrakten te skriuwen op RIDE en RIDE4DAPPS. Diel 2 (DAO - Desintralisearre autonome organisaasje)

Litte wy besykje werom te lûken fia weromlûken:

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

It skript wurket en wy hawwe it 2e punt útfûn!

Stage 4. Meitsje in DAO mei stimmen

Spitigernôch biedt de RIDE-taal noch net de mooglikheid om mei kolleksjes te wurkjen (wurdboekwurdboeken, iterators, ferlytsers, ensfh.). Lykwols, foar alle operaasjes mei platte kolleksjes kaai-wearde wy kinne in systeem ûntwerpe foar it wurkjen mei snaren, neffens toetsen en har ûntsiferje.

Stringen binne heul maklik te ferbinen; snaren kinne wurde skieden troch yndeksen.
Litte wy in tekenrige sammelje en analysearje as testfoarbyld en kontrolearje hoe't dit de útkomst fan 'e transaksje beynfloedet.
Wy hawwe fêstlein oer it feit dat Alice de Transfer-transaksje net koe ûndertekenje, om't dizze mooglikheid waard blokkearre yn @verifier foar dit soarte transaksje.

Litte wy oefenje mei snaren en dan oplosse dit.

RIDE Strings

De transaksje is mooglik wer, wy witte hoe te wurkjen mei snaren.
Learje om Waves smart kontrakten te skriuwen op RIDE en RIDE4DAPPS. Diel 2 (DAO - Desintralisearre autonome organisaasje)


Yn totaal hawwe wy alles nedich om komplekse logika te skriuwen DAO dApp.

Data Transaksjes

Gegevenstransaksjes:
"De maksimale grutte foar in kaai is 100 tekens, en in kaai kin willekeurige Unicode-koadepunten befetsje, ynklusyf spaasjes en oare net-printbere symboalen. Stringwearden hawwe in limyt fan 32,768 bytes en it maksimum oantal mooglike yngongen yn gegevenstransaksjes is 100. Oer it algemien is de maksimale grutte fan in gegevenstransaksje sawat 140kb - foar referinsje, hast krekt de lingte fan Shakespeare's toanielstik 'Romeo en Julia' '."

Wy meitsje in DAO mei de folgjende betingsten:
Om in startup te ûntfangen finansiering troch te skiljen getFunds() de stipe fan op syn minst 2 dielnimmers - DAO ynvestearders - is nedich. Ôfdraaie it sil mooglik wêze krekt safolle as it totaal oanjûn op stimme DAO eigners.

Litte wy 3 soarten toetsen meitsje en logika tafoegje foar it wurkjen mei saldo's yn 2 nije funksjes stimme en getFunds:
xx…xx_ia = ynvestearders, beskikber lykwicht (stim, boarch, weromlûken)
xx…xx_sv = startups, oantal stimmen (stim, getFunds)
xx…xx_sf = startups, oantal stimmen (stim, getFunds)
xx…xx = iepenbier adres (35 tekens)

Tink derom dat wy yn 'e stimming ferskate fjilden tagelyk moasten bywurkje:

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

WriteSet lit ús ferskate records tagelyk binnen ien meitsje invokeScript transaksjes.

Dit is hoe't it liket yn 'e kaai-wearde opslach fan' e DAO dApp, neidat Bob en Cooper oanfolle ia- ôfsettings:
Learje om Waves smart kontrakten te skriuwen op RIDE en RIDE4DAPPS. Diel 2 (DAO - Desintralisearre autonome organisaasje)

Us boarchfunksje is wat feroare:
Learje om Waves smart kontrakten te skriuwen op RIDE en RIDE4DAPPS. Diel 2 (DAO - Desintralisearre autonome organisaasje)

No komt it wichtichste momint yn 'e aktiviteiten fan' e DAO - stim foar projekten dy't finansierd wurde.

Bob stimt foar Neli's 500000 wavelets-projekt:

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

Learje om Waves smart kontrakten te skriuwen op RIDE en RIDE4DAPPS. Diel 2 (DAO - Desintralisearre autonome organisaasje)

Yn 'e gegevenswinkel sjogge wy alle nedige yngongen foar Neli's adres:
Learje om Waves smart kontrakten te skriuwen op RIDE en RIDE4DAPPS. Diel 2 (DAO - Desintralisearre autonome organisaasje)
Cooper stimde ek foar it Neli-projekt.
Learje om Waves smart kontrakten te skriuwen op RIDE en RIDE4DAPPS. Diel 2 (DAO - Desintralisearre autonome organisaasje)

Litte we ris nei de funksje koade getFunds. Neli moat in minimum fan 2 stimmen sammelje om jild út de DAO werom te heljen.
Learje om Waves smart kontrakten te skriuwen op RIDE en RIDE4DAPPS. Diel 2 (DAO - Desintralisearre autonome organisaasje)

Neli sil de helte fan it oan har tawiisde bedrach weromlûke:

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

Learje om Waves smart kontrakten te skriuwen op RIDE en RIDE4DAPPS. Diel 2 (DAO - Desintralisearre autonome organisaasje)

Se slagget, dat is, DAO wurket!

Wy seagen nei it proses fan it meitsjen fan in DAO yn 'e taal RIDE4DAPPS.
Yn 'e folgjende dielen sille wy in tichterby besjen op koade refactoring en case-testen.

Folsleine ferzje fan de koade yn 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
    }
}

Earste diel
Koade op GitHub
Waves RIDE IDE
Oankundiging fan it subsydzjeprogramma

Boarne: www.habr.com

Add a comment