RIDE eta RIDE4DAPPS-en Waves kontratu adimendunak nola idazten ikastea. 2. zatia (DAO - Erakunde autonomo deszentralizatua)

RIDE eta RIDE4DAPPS-en Waves kontratu adimendunak nola idazten ikastea. 2. zatia (DAO - Erakunde autonomo deszentralizatua)

Hola a todos!

Π’ lehenengoa zatian, dApp (aplikazio deszentralizatua) nola sortu eta nola lan egin aztertu dugu Waves RIDE IDE.

Proba dezagun orain desmuntatutakoa apur bat Adibidez.

3. etapa. dApp kontua probatzen

RIDE eta RIDE4DAPPS-en Waves kontratu adimendunak nola idazten ikastea. 2. zatia (DAO - Erakunde autonomo deszentralizatua)

Zer arazo berehala Alicerekin ahotsetara dApp Kontua?
Lehenik eta behin:
Boob eta Cooper-ek ustekabean dirua bidal ditzakete dApp helbide batera normal bat erabiliz transferitzeko transakzioak eta, beraz, ezin izango dira atzera sartu.

Bigarrenik:
Ez dugu inola ere mugatzen Alice funtsak ateratzea Boob eta/edo Cooperren baimenik gabe. Geroztik, arreta jarri egiaztatzeko, Aliceren transakzio guztiak exekutatu egingo dira.

Konpon dezagun 2 Alice debekatuz transferitzeko transakzioak. Inplementatu zuzendutako scripta:
RIDE eta RIDE4DAPPS-en Waves kontratu adimendunak nola idazten ikastea. 2. zatia (DAO - Erakunde autonomo deszentralizatua)
οΏΌ
DApp Alice eta bere sinadurarekin txanponak erretiratzen saiatzen ari gara. Errore bat jasoko dugu:
RIDE eta RIDE4DAPPS-en Waves kontratu adimendunak nola idazten ikastea. 2. zatia (DAO - Erakunde autonomo deszentralizatua)

Erretiratzearen bidez erretiratzen saiatzen:

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

Gidoiak funtzionatzen du eta 2. puntua asmatu dugu!

4. etapa. Sortu DAO bat bozketarekin

Zoritxarrez, RIDE hizkuntzak ez du oraindik bildumekin lan egiteko gaitasunik ematen (hiztegiak, hiztegiak, iteratzaileak, murriztaileak, etab.). Hala ere, bilduma lauen gaineko edozein eragiketetarako gako-balioa kateekin lan egiteko sistema bat diseina dezakegu, hurrenez hurren gakoekin eta haien deszifraketarekin.

Kateak kateatzen oso errazak dira, kateak indizeen bidez bereiz daitezke.
Bildu eta analiza ditzagun katea test kasu gisa eta egiaztatu horrek transakzioaren emaitzan nola eragingo duen.
Alicek Transferentzia transakzioa sinatu ezin zuela erabaki genuen, aukera hori @verifier-en blokeatuta zegoen transakzio mota honetarako.

Praktikatu dezagun kateekin eta ebatzi dezagun.

RIDE kateak

Transakzioa posible da berriro, kateekin lan egiten badakigu.
RIDE eta RIDE4DAPPS-en Waves kontratu adimendunak nola idazten ikastea. 2. zatia (DAO - Erakunde autonomo deszentralizatua)

οΏΌ
Guztira, logika konplexua idazteko behar duzun guztia dugu DAO dApp.

Datu-transakzioak

Datu transakzioak:
"Gako baten gehienezko tamaina 100 karakterekoa da, eta gako batek Unicode kode puntu arbitrarioak izan ditzake zuriuneak eta inprimagarriak ez diren beste sinbolo batzuk barne. Kate-balioek 32,768 byte-ko muga dute eta datu-transakzioan sartze posibleen gehienezko kopurua 100 da. Orokorrean, datu-transakzio baten gehienezko tamaina 140 kb ingurukoa da - erreferentzia gisa, Shakespeareren "Romeo eta Julieta" antzezlanaren ia zehatz-mehatz. '."

DAO bat sortzen dugu baldintza hauekin:
Startup batek deituz finantzaketa lor dezan lortu funtsak() gutxienez 2 parte-hartzaileren laguntza - DAO inbertitzaileak behar da. erretiratuko gainean adierazitako batura bezainbeste posible izango da bozketa DAO jabeak.

Egin ditzagun 3 gako mota eta gehitu logika saldoekin lan egiteko 2 funtzio berritan bozkatu eta lortuFunds:
xx...xx_ia = inbertitzaileak, saldo erabilgarria (botoa, gordailua, kentzea)
xx...xx_sv = startup-ak, boto kopurua (bozkatu, lortu funtsak)
xx...xx_sf = startup-ak, boto kopurua (bozkatu, lortu funtsak)
xx…xx = helbide publikoa (35 karaktere)

Oharra Bozketan hainbat eremu aldi berean eguneratu behar ditugula:

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

WriteSet-ek hainbat erregistro aldi berean egiteko aukera ematen digu bakar baten barruan invokeScript transakzioak.

Honela ikusten da DAO dApp-ren gako-balioen biltegian, Bob eta Cooper-ek bete ondoren ia- Gordailuak:
RIDE eta RIDE4DAPPS-en Waves kontratu adimendunak nola idazten ikastea. 2. zatia (DAO - Erakunde autonomo deszentralizatua)

Gure gordailu-funtzioa zertxobait aldatu da:
RIDE eta RIDE4DAPPS-en Waves kontratu adimendunak nola idazten ikastea. 2. zatia (DAO - Erakunde autonomo deszentralizatua)

Orain dator DAOren jardueren unerik garrantzitsuena - bozkatu finantzaketa-proiektuetarako.

Bob-ek Neli proiektuaren alde bozkatu du 500000 uhinetan:

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

RIDE eta RIDE4DAPPS-en Waves kontratu adimendunak nola idazten ikastea. 2. zatia (DAO - Erakunde autonomo deszentralizatua)

Datu biltegian, Neli helbiderako beharrezko sarrera guztiak ikusiko ditugu:
RIDE eta RIDE4DAPPS-en Waves kontratu adimendunak nola idazten ikastea. 2. zatia (DAO - Erakunde autonomo deszentralizatua)
Cooperek ere Neli proiektuaren alde bozkatu zuen.
RIDE eta RIDE4DAPPS-en Waves kontratu adimendunak nola idazten ikastea. 2. zatia (DAO - Erakunde autonomo deszentralizatua)

Ikus dezagun funtzioaren kodea lortu funtsak. Nelik gutxienez 2 boto bildu behar ditu DAOtik funtsak atera ahal izateko.
RIDE eta RIDE4DAPPS-en Waves kontratu adimendunak nola idazten ikastea. 2. zatia (DAO - Erakunde autonomo deszentralizatua)

Nelik agindutako zenbatekoaren erdia aterako du:

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

RIDE eta RIDE4DAPPS-en Waves kontratu adimendunak nola idazten ikastea. 2. zatia (DAO - Erakunde autonomo deszentralizatua)

Lortzen du, hau da, DAOk funtzionatzen du!

Hizkuntzan DAO bat sortzeko prozesua aztertu dugu RIDE4DAPPS.
Ondorengo zatietan, kodearen birfaktorizazioa eta kasuen probak aztertuko ditugu.

Kode osoa sartu 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
    }
}

Lehenengo zatian
Github-en kodea
Waves RIDE IDE
Diru-laguntzen programaren iragarkia

Iturria: www.habr.com

Gehitu iruzkin berria