Të mësojmë të shkruajmë kontrata smart Waves në RIDE dhe RIDE4DAPPS. Pjesa 2 (DAO - Organizata e Autonomisë së Decentralizuar)

Të mësojmë të shkruajmë kontrata smart Waves në RIDE dhe RIDE4DAPPS. Pjesa 2 (DAO - Organizata e Autonomisë së Decentralizuar)

Përshëndetje të gjithëve!

e parë pjesës, ne shqyrtuam në detaje se si të krijojmë dhe punojmë me dApp (aplikacion të decentralizuar) në Waves RIDE IDE.

Tani le të testojmë pak atë që kemi analizuar është.

Hapi 3. Testimi i llogarisë dApp

Të mësojmë të shkruajmë kontrata smart Waves në RIDE dhe RIDE4DAPPS. Pjesa 2 (DAO - Organizata e Autonomisë së Decentralizuar)

Cilat probleme bien menjëherë në sy me Alice? dApp Llogaria?
Së pari:
Boob dhe Cooper mund të dërgojnë aksidentalisht fonde në adresën e dApp përmes një transfer transaksioni dhe, kështu, nuk do të mund t'i marrin përsëri ato.

Së dyti:
Ne nuk e kufizojmë Alice të nxjerrë fonde pa marrëveshje me Boob dhe/ose Cooper. Në mënyrë që, vini re se verifikimi, të gjitha transaksionet nga Alice do të ekzekutohen.

Le të korrigjojmë këtë të dytë, duke ndaluar Alice transfer transaksionet. Pjesët ndërtuese të skriptit të riparuar:
Të mësojmë të shkruajmë kontrata smart Waves në RIDE dhe RIDE4DAPPS. Pjesa 2 (DAO - Organizata e Autonomisë së Decentralizuar)

Dërgojmë kërkesën për të nxjerrë monedhat nga dApp Alice me nënshkrimin e saj. Marrim një gabim:
Të mësojmë të shkruajmë kontrata smart Waves në RIDE dhe RIDE4DAPPS. Pjesa 2 (DAO - Organizata e Autonomisë së Decentralizuar)

Dërgojmë përmes tërheqjes:

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

Skripti funksionon dhe ne e zgjidhëm pikën e dytë!

Hapi 4. Krijimi i DAO me votim

Fatkeqësisht, gjuha RIDE për momentin nuk ofron mundësi për të punuar me koleksione (fjalorë-fjalorësh, iteratorë, reduktues dhe të tjera). Megjithatë, për çdo operacion me koleksione të thjeshta key-value ne mund të projektrojmë një sistem pune me strinja, përkatësisht me çelësa dhe dekriptime.

Strinjave është shumë e lehtë t'i bashkojmë, strinjave mund të ndahen sipas indekseve.
Le të marrim si një shembull testimi të bashkojmë dhe zbërthejmë një string dhe të shohim se si ndikon kjo në rezultatin e transaksionit.
Ne u ndalëm në faktin që Alice nuk mund të nënshkruante transaksionin Transfer, pasi kjo mundësi ishte bllokuar në @verifier për këtë lloj transaksioni.

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

RIDE Strinjave

Transaksioni është përsëri i mundshëm, ne dimë si të punojmë me strinjave.
Të mësojmë të shkruajmë kontrata smart Waves në RIDE dhe RIDE4DAPPS. Pjesa 2 (DAO - Organizata e Autonomisë së Decentralizuar)


Pra, kemi të gjitha nevojat për të shkruar një 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ë koodesh Unicode të rastësishme përfshirë hapësira dhe simbole të tjera jo-printueshëm. Vlerat e strinjave kanë një kufi prej 32,768 bytes dhe numri maksimale i mundshëm i hyrjeve në një transaksion të dhënash është 100. Përveç kësaj, madhësia maksimale e një transaksioni të dhënash është rreth 140kb — për reference, pothuajse saktësisht sa gjatësia e dramës së Shakespeare-në ‘Romeo dhe Zhulieta’.”

Krijojmë një DAO me kushtet e mëposhtme:
Për të marrë financim startup, duke thirrur getFunds() duhet të ketë mbështetje nga të paktën 2 pjesëtarë — investitorët e DAO. Shfaq do të mund të jetë pikërisht aq sa në total u deklarua në votim të zotërve të DAO.

Le të krijojmë 3 lloje çelësh dhe të shtojmë logjikën për punën me balancat në 2 funksione të reja: vote dhe getFunds:
xx…xx_ia = investitorët, bilanci i arritshë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)

Vini re se në Vote na nevojitet të azhurnojmë menjëherë disa fusha:

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

WriteSet na lejon të bëjmë disa shënime brenda një invokeScript transaksioni.

Ja si duket në depozitën key-value të DAO dApp, pasi Bob dhe Cooper plotësuan ia-depozitat:
Të mësojmë të shkruajmë kontrata smart Waves në RIDE dhe RIDE4DAPPS. Pjesa 2 (DAO - Organizata e Autonomisë së Decentralizuar)

Funksioni i depozitës ka ndryshuar pak:
Të mësojmë të shkruajmë kontrata smart Waves në RIDE dhe RIDE4DAPPS. Pjesa 2 (DAO - Organizata e Autonomisë së Decentralizuar)

Tani po arrin momenti 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: []}))

Të mësojmë të shkruajmë kontrata smart Waves në RIDE dhe RIDE4DAPPS. Pjesa 2 (DAO - Organizata e Autonomisë së Decentralizuar)

Në depozitën e të dhënave shohim të gjitha shënimet e nevojshme për adresën Neli:
Të mësojmë të shkruajmë kontrata smart Waves në RIDE dhe RIDE4DAPPS. Pjesa 2 (DAO - Organizata e Autonomisë së Decentralizuar)
Cooper gjithashtu votoi për projektin Neli.
Të mësojmë të shkruajmë kontrata smart Waves në RIDE dhe RIDE4DAPPS. Pjesa 2 (DAO - Organizata e Autonomisë së Decentralizuar)

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.
Të mësojmë të shkruajmë kontrata smart Waves në RIDE dhe RIDE4DAPPS. Pjesa 2 (DAO - Organizata e Autonomisë së Decentralizuar)

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: []}))

Të mësojmë të shkruajmë kontrata smart Waves në RIDE dhe RIDE4DAPPS. Pjesa 2 (DAO - Organizata e Autonomisë së Decentralizuar)

Ajo ia del, domethënë DAO funksionon!

Ne shqyrtuam procesin e krijimit të DAO në gjuhën RIDE4DAPPS.
Në pjesët e ardhshme 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 i programit të granteve

Burimi: habr.com

Blini hostim të besueshëm për faqe interneti me mbrojtje DDoS, serverë VPS VDS 🔥 Blini hostim të besueshëm për faqe interneti me mbrojtje DDoS, serverë VPS VDS - ProHoster