Õpime kirjutama Waves’i nutilepinguid RIDE ja RIDE4DAPPS keeles. 2. osa (DAO – detsentraliseeritud autonoomne organisatsioon)

Õpime kirjutama Waves’i nutilepinguid RIDE ja RIDE4DAPPS keeles. 2. osa (DAO – detsentraliseeritud autonoomne organisatsioon)

Tere kÔigile!

Uues esimene osa, me kĂ€sitleme ĂŒksikasjalikult, kuidas luua ja töötada dApp-i (detsentraliseeritud rakenduse) juures Waves RIDE IDE.

Testime nĂŒĂŒd veidi lahti vĂ”etud nĂ€ide.

Etapp 3. dApp konto testimine

Õpime kirjutama Waves’i nutilepinguid RIDE ja RIDE4DAPPS keeles. 2. osa (DAO – detsentraliseeritud autonoomne organisatsioon)

Millised probleemid esmapilgul Alice'i juures silma hakkavad dApp Konto?
Esiteks:
Boob ja Cooper vĂ”ivad juhuslikult saata dApp aadressile raha tavalise ĂŒlekandmine tehingu kaudu ja seega ei pÀÀse nad sellele enam juurde.

Teiseks:
Me ei piira Alice'i raha vÀljavÔtmist Boobi vÔi Cooperiga kooskÔlastamise nÔudmisest. Pidage meeles, et kÔik Alice'i tehingud tÀidetakse.

Parandame teise, keelates Alice'il ĂŒlekandmine tehingud. Rakendame parandatud skripti:
Õpime kirjutama Waves’i nutilepinguid RIDE ja RIDE4DAPPS keeles. 2. osa (DAO – detsentraliseeritud autonoomne organisatsioon)
ïżŒ
Proovime vÀljavÔtteid Alice'i dAppist ja tema allkirjast. Saame vea:
Õpime kirjutama Waves’i nutilepinguid RIDE ja RIDE4DAPPS keeles. 2. osa (DAO – detsentraliseeritud autonoomne organisatsioon)

Proovime vÀljavÔttes:

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

Skript töötab ja 2. punkt on selge!

Etapp 4. Loome DAO hÀÀltega

Kahjuks ei saa RIDE keeles praegu töötada kollektsioonidega (sĂ”nastikud, iteratorid, vĂ€hendajad jne). Siiski, kĂ”iki operatsioone tasapinnaliste kollektsioonidega key-value saame planeerida sĂŒstemaatika stringide, vastavalt vĂ”tmete ja nende deĆĄifreerimisega.

Stringe on vÀga lihtne konkateneerida, stringe saab jagada indeksite jÀrgi.
Kogume ja analĂŒĂŒsime stringi testnĂ€itena ning kontrollime, kuidas see mĂ”jutab tehingu tulemust.
Keskendume sellele, et Alice ei saanud Transfer tehingut allkirjastada, kuna see vÔimalus oli @verifieris blokeeritud selliste tehingute jaoks.

Haarame stringide kasutamisega ja seejÀrel lubame selle.

RIDE stringid

Tehing on taas vÔimalik, oskame töötada stringidega.
Õpime kirjutama Waves’i nutilepinguid RIDE ja RIDE4DAPPS keeles. 2. osa (DAO – detsentraliseeritud autonoomne organisatsioon)

ïżŒ
KokkuvÔttes on meil kÔik vajalik keerulise loogika kirjutamiseks DAO dApp.

Andmete tehingud

Andmete tehingud:
„VĂ”tme maksimaalne suurus on 100 tĂ€hemĂ€rki, ja vĂ”tmel vĂ”ivad olla juhuslikud Unicode koodipunktid, sealhulgas tĂŒhikud ja muud mitteprinditavad sĂŒmbolid. Stringi vÀÀrtustel on piirang 32 768 baiti ja andmete tehingus on maksimaalne sisestuste arv 100. Üldiselt on andmete tehingu maksimaalne suurus umbes 140 kb — viiteks, justkui William Shakespeare'i nĂ€idend 'Romeo ja Julia' pikkus.”

Loome DAO jÀrgmiste tingimustega:
Et startup saaks rahastust, kutsudes esile getFunds() on vajalik vĂ€hemalt 2 DAO osalise – investorite toetust. VĂ€ljasta saab olema tĂ€pselt nii palju, kui kokku hÀÀletati DAO omanike poolt. ĐČĐ»Đ°ĐŽĐ”Đ»ŃŒŃ†Ń‹ DAO.

Teeme 3 tĂŒĂŒpi vĂ”tmeid ja lisame tasakaalude haldamise loogika kahe uue funktsiooni, vote ja getFunds, kaudu:
xx
xx_ia = investorid, saadaval tasakaal (vote, deposit, withdrawal)
xx
xx_sv = startupid, hÀÀlte arv (vote, getFunds)
xx
xx_sf = startupid, hÀÀlte arv (vote, getFunds)
xx
xx = avalik aadress (35 tÀhte)

Pange tÀhele, et Vote'is pidi me vÀrskendama korraga mitmeid vÀlju:

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

WriteSet vĂ”imaldab meil teha korraga mitu kirjet ĂŒhe invokeScript tehingu raames.

Nii see vÀlja nÀeb DAO dApp key-value salvestuses, pÀrast seda, kui Bob ja Cooper on fondi tÀiendanud ia-deposiid:
Õpime kirjutama Waves’i nutilepinguid RIDE ja RIDE4DAPPS keeles. 2. osa (DAO – detsentraliseeritud autonoomne organisatsioon)

Deposiidi funktsioon on meil pisut muutunud:
Õpime kirjutama Waves’i nutilepinguid RIDE ja RIDE4DAPPS keeles. 2. osa (DAO – detsentraliseeritud autonoomne organisatsioon)

NĂŒĂŒd on kĂ€es kĂ”ige olulisem moment DAO tegevuses — hÀÀletamine projektide rahastamise poolt.

Bob hÀÀletab projekti Neli poolt 500000 waveletiga:

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

Õpime kirjutama Waves’i nutilepinguid RIDE ja RIDE4DAPPS keeles. 2. osa (DAO – detsentraliseeritud autonoomne organisatsioon)

Andmehoidlas nÀeme kÔik vajalikud kirjed Neli aadressi jaoks:
Õpime kirjutama Waves’i nutilepinguid RIDE ja RIDE4DAPPS keeles. 2. osa (DAO – detsentraliseeritud autonoomne organisatsioon)
Cooper hÀÀletas samuti projekti Neli poolt.
Õpime kirjutama Waves’i nutilepinguid RIDE ja RIDE4DAPPS keeles. 2. osa (DAO – detsentraliseeritud autonoomne organisatsioon)

Vaatame koodi funktsioonist getFunds. Neli peab koguma vÀhemalt 2 hÀÀlt, et saada vÔimalus eraldada vahendeid DAO-st.
Õpime kirjutama Waves’i nutilepinguid RIDE ja RIDE4DAPPS keeles. 2. osa (DAO – detsentraliseeritud autonoomne organisatsioon)

Neli kavatseb vÀlja vÔtta poole talle usaldatud summast:

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

Õpime kirjutama Waves’i nutilepinguid RIDE ja RIDE4DAPPS keeles. 2. osa (DAO – detsentraliseeritud autonoomne organisatsioon)

Tal Ônnestub see, mis tÀhendab, et DAO töötab!

Me kÀsitlesime DAO loomise protsessi keeles RIDE4DAPPS.
JÀrgmistes osades kÀsitleme koodi refaktoreerimist ja testimist.

Koodi tÀisversioon 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
    }
}

Esimene osa
Kood GitHubis
Waves RIDE IDE
Grantide programmi teadaanne

Allikas: habr.com

Osta usaldusvÀÀrne hostimine veebilehtede jaoks DDoS-i kaitsega, VPS VDS serverid đŸ”„ Osta usaldusvÀÀrne hostimine veebilehtede jaoks DDoS-i kaitsega, VPS VDS serverid | ProHoster