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!

Në 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 hosting tĂ« besueshĂ«m pĂ«r faqe interneti me mbrojtje nga DDoS, serverĂ« VPS VDS đŸ”„ Blini hosting tĂ« besueshĂ«m pĂ«r faqe interneti me mbrojtje nga DDoS, serverĂ« VPS VDS | ProHoster