MĂ«sojmĂ« tĂ« shkruajmĂ« kontrata smart Waves nĂ« RIDE dhe RIDE4DAPPS. Pjesa 2 (DAO — Organizata Autonomous Qendrore)

MĂ«sojmĂ« tĂ« shkruajmĂ« kontrata smart Waves nĂ« RIDE dhe RIDE4DAPPS. Pjesa 2 (DAO — Organizata Autonomous Qendrore)

Përshëndetje të gjithëve!

Në pjesën e parë Këtu kemi shqyrtuar në detaje se si të krijojmë dhe punojmë me një dApp (aplikacion decentralizuar) në Waves RIDE IDE.

Tani le të testojmë pak atë që kemi shqyrtuar shembull.

Hapi 3. Testimi i llogarisë dApp

MĂ«sojmĂ« tĂ« shkruajmĂ« kontrata smart Waves nĂ« RIDE dhe RIDE4DAPPS. Pjesa 2 (DAO — Organizata Autonomous Qendrore)

ÇfarĂ« shqetĂ«simesh bien menjĂ«herĂ« nĂ« sy me Alice? dApp Llogaria?
E para:
Boob dhe Cooper mund të dërgojnë aksidentalisht fonde në adresën e dApp me anë të një transfer transaksioni dhe kështu nuk do të mund të kthejnë ato mbrapsht.

SĂ« dyti:
Ne nuk i kufizojmë Alice në tërheqjen e fondeve pa miratimin e Boob ose (dhe) Cooper. Vini re, për të verifikuar, të gjitha transaksionet nga Alice do të ekzekutohen.

Le të rregullojmë të dytën, duke ndaluar Alice transfer transaksionet. Bëjmë deploy skenarin e rregulluar:
MĂ«sojmĂ« tĂ« shkruajmĂ« kontrata smart Waves nĂ« RIDE dhe RIDE4DAPPS. Pjesa 2 (DAO — Organizata Autonomous Qendrore)
ïżŒ
Provojmë të tërheqim monedha nga dApp Alice me nënshkrimin e saj. Marrim një gabim:
MĂ«sojmĂ« tĂ« shkruajmĂ« kontrata smart Waves nĂ« RIDE dhe RIDE4DAPPS. Pjesa 2 (DAO — Organizata Autonomous Qendrore)

Provojmë të tërheqim përmes withdraw:

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

Skenari funksionon dhe me pikën e dytë ne u sqaruam!

Hapi 4. Krijojmë DAO me votim

Fatkeqësisht, në gjuhën RIDE akoma nuk janë parashikuar mundësitë për të punuar me koleksione (fjalorë-fjalorësh, iteratorë, reduktues dhe të tjera). Megjithatë, për çdo operacion me koleksione të thjeshta çelës-vlerë ne mund të krijojmë një sistem pune me vargje, përkatësisht me çelësat dhe dekodimin e tyre.

Të dhënat janë shumë të lehta për t'u lidhur, vargjet mund të ndahen sipas indekseve.
Le të krijojmë dhe shqyrtojmë një varg si një shembull testimi dhe të shohim si do të ndikojë në rezultatin e transaksionit.
Ne e përfunduam duke thënë se Alice nuk mund të nënshkruante një transaksion Transfer, pasi kjo mundësi ishte bllokuar në @verifier për këtë lloj transaksioni.

Le të ushtrojmë me vargjet dhe pastaj ta lejojmë këtë.

RIDE Strings

Transaksioni është përsëri i mundur, ne dimë si të punojmë me vargjet.
MĂ«sojmĂ« tĂ« shkruajmĂ« kontrata smart Waves nĂ« RIDE dhe RIDE4DAPPS. Pjesa 2 (DAO — Organizata Autonomous Qendrore)

ïżŒ
Në përmbledhje, kemi gjithçka të nevojshme për të shkruar logjikë të komplikuar DAO dApp.

Transaksionet e të dhënave

Transaksionet e të dhënave:
“MadhĂ«sia maksimale pĂ«r njĂ« çelĂ«s Ă«shtĂ« 100 karaktere, dhe njĂ« çelĂ«s mund tĂ« pĂ«rmbajĂ« pikĂ«kodet Unicode tĂ« rastit, duke pĂ«rfshirĂ« hapĂ«sirat dhe simbolet e tjera jo-printuese. Vlerat e vargjeve kanĂ« njĂ« kufi prej 32,768 byte dhe numri maksimal i hyrjeve tĂ« mundshme nĂ« transaksionet e tĂ« dhĂ«nave Ă«shtĂ« 100. NĂ« pĂ«rgjithĂ«si, madhĂ«sia maksimale e njĂ« transaksioni tĂ« dhĂ«nash Ă«shtĂ« rreth 140kb — pĂ«r referencĂ«, pothuajse saktĂ«sisht gjatĂ«si e dramĂ«s sĂ« Shakespeare 'Romeo dhe Juliet'.

Krijojmë DAO me kushtet e mëposhtme:
PĂ«r tĂ« marrĂ« financim pĂ«r njĂ« startup, duke thirrur getFunds() nevojitet mbĂ«shtetje nga tĂ« paktĂ«n 2 pjesĂ«marrĂ«s — investitorĂ« DAO. Shfaqni mund tĂ« jetĂ« saktĂ«sisht aq sa u shpreh nĂ« sumĂ« nĂ« votim pronarĂ«t e DAO.

Le të krijojmë 3 lloje çelësh dhe të shtojmë logjikë për punën me bilancet në 2 funksione të reja, vote dhe getFunds:
xx
xx_ia = investitorët, bilanci i disponueshëm (vote, deposit, withdrawal)
xx
xx_sv = startupet, numri i votave (vote, getFunds)
xx
xx_sf = startupet, numri i votave (vote, getFunds)
xx
xx = adresa publike (35 karaktere)

Vëreni se në Vote na duhej të përditësonim disa fusha menjëherë:

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

WriteSet na lejon të bëjmë disa regjistrime në kuadër të një invokeScript transaksioni.

Kështu duket në depozitë të dhënash DAO dApp, pas ia-depozitave:
MĂ«sojmĂ« tĂ« shkruajmĂ« kontrata smart Waves nĂ« RIDE dhe RIDE4DAPPS. Pjesa 2 (DAO — Organizata Autonomous Qendrore)

Funksioni i depozitës na u ndryshua pak:
MĂ«sojmĂ« tĂ« shkruajmĂ« kontrata smart Waves nĂ« RIDE dhe RIDE4DAPPS. Pjesa 2 (DAO — Organizata Autonomous Qendrore)

Tani po arrijmĂ« momentin mĂ« tĂ« rĂ«ndĂ«sishĂ«m nĂ« aktivitetin e DAO — votimi pĂ«r projektet pĂ«r financim.

Bob voton për projektin Neli me 500000 wavelets:

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

MĂ«sojmĂ« tĂ« shkruajmĂ« kontrata smart Waves nĂ« RIDE dhe RIDE4DAPPS. Pjesa 2 (DAO — Organizata Autonomous Qendrore)

Në depozitën e dhënave ne shohim të gjithë regjistrimet e nevojshme për adresën Neli:
MĂ«sojmĂ« tĂ« shkruajmĂ« kontrata smart Waves nĂ« RIDE dhe RIDE4DAPPS. Pjesa 2 (DAO — Organizata Autonomous Qendrore)
Cooper gjithashtu votoi për projektin Neli.
MĂ«sojmĂ« tĂ« shkruajmĂ« kontrata smart Waves nĂ« RIDE dhe RIDE4DAPPS. Pjesa 2 (DAO — Organizata Autonomous Qendrore)

Le të shohim kodin e funksionit getFunds. Neli duhet të mbledhë të paktën 2 vota për të pasur mundësi të tërheqë fonde nga DAO.
MĂ«sojmĂ« tĂ« shkruajmĂ« kontrata smart Waves nĂ« RIDE dhe RIDE4DAPPS. Pjesa 2 (DAO — Organizata Autonomous Qendrore)

Neli planifikon të tërheqë gjysmën e shumës së besuar:

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

MĂ«sojmĂ« tĂ« shkruajmĂ« kontrata smart Waves nĂ« RIDE dhe RIDE4DAPPS. Pjesa 2 (DAO — Organizata Autonomous Qendrore)

Ajo e arrin këtë, që do të thotë që DAO funksionon!

Ne shqyrtuam procesin e krijimit të DAO në gjuhën RIDE4DAPPS.
Në pjesët në vazhdim do të merremi më në detaje me refaktorizimin e kodit dhe testimin e rasteve.

Versioni i plotë i kodit në 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
    }
}

Pjesa e parë
Kodi në GitHub
Waves RIDE IDE
Njoftimi për programin e granteve

Burimi: habr.com

Bleni hostim tĂ« besueshĂ«m pĂ«r faqe me mbrojtje nga DDoS, serverĂ« VPS VDS đŸ”„ Bleni hostim tĂ« besueshĂ«m pĂ«r faqe me mbrojtje nga DDoS, serverĂ« VPS VDS | ProHoster