Õppime kirjutama Wavesi nutikaid lepinguid RIDE ja RIDE4DAPPS. Osa 2 (DAO — detsentraliseeritud autonoomne organisatsioon)

Õppime kirjutama Wavesi nutikaid lepinguid RIDE ja RIDE4DAPPS. Osa 2 (DAO — detsentraliseeritud autonoomne organisatsioon)

Tere kÔigile!

V esimese osa jooksul vaatlesime pÔhjalikult, kuidas luua ja töötada dApp (detsentraliseeritud rakendus) Waves RIDE IDE.

Katsetame nĂŒĂŒd veidi Ă€ra vĂ”etud an example.

Etapp 3. dApp konto testimine

Õppime kirjutama Wavesi nutikaid lepinguid RIDE ja RIDE4DAPPS. Osa 2 (DAO — detsentraliseeritud autonoomne organisatsioon)

Millised probleemid viskuvad kohe silma Alice dApp konto?
Esiteks:
Boob ja Cooper vÔivad juhuslikult saata dApp aadressile vahendeid tavatransaktsiooni kaudu ja seega ei saa nad neile enam juurde pÀÀseda. transfer Teiseks:

Me ei piira kuidagi Alice'i vahendite tÔmbamist ilma Boobi vÔi Cooperiga kokku leppimata. Pange tÀhele, et kÔik Alice'i tehingud tÀidetakse.
Parandame teise, keelates Alice'i

tehingud. Juurutame parandatud skripti: transfer Proovime vĂ€lja vĂ”tta mĂŒnte Alice'i ja tema allkirjaga. Saame vea:
Õppime kirjutama Wavesi nutikaid lepinguid RIDE ja RIDE4DAPPS. Osa 2 (DAO — detsentraliseeritud autonoomne organisatsioon)
ïżŒ
Proovime vÀlja vÔtta withdraw kaudu:
Õppime kirjutama Wavesi nutikaid lepinguid RIDE ja RIDE4DAPPS. Osa 2 (DAO — detsentraliseeritud autonoomne organisatsioon)

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

Skript töötab ning saime teise punkti selgeks!

Etapp 4. Loome DAO koos hÀÀletamisega

Samm 4. Loome hÀÀletamise DAO

Kahjuks ei ole RIDE keeles yet olemas vĂ”imalusi kollektiividega (sĂ”nastikud-sĂ”nastiked, iteratsioonid, reduktorid jne) töötamiseks. Siiski, kĂ”ikide toimingute puhul tasapinnaliste kollektsioonidega vĂ”ti-vÀÀrtus saame kavandada sĂŒsteemi, mis tegeleb stringide, seega ka vĂ”tmete ja nende deĆĄifreerimisega.

Stringe on vĂ€ga lihtne ĂŒhendama, stringe saab indekseid mööda jagada.
LÀhme testnÀitena stringi koostama ja lahendame selle, et vaadata, kuidas see mÔjutab tehingu tulemust.
JĂ”udsime sinnani, et Alice ei saanud Transfer tehingut allkirjastada, kuna see vĂ”imalus oli @verifier'is selle tĂŒĂŒbi tehingute jaoks blokeeritud.

Harjutame stringidega ja lahendame siis selle kĂŒsimuse.

RIDE stringid

Tehing on jÀlle vÔimalik, saame stringidega töötada.
Õppime kirjutama Wavesi nutikaid lepinguid RIDE ja RIDE4DAPPS. Osa 2 (DAO — detsentraliseeritud autonoomne organisatsioon)

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

Andmete tehingud

Andmete tehingud:
„VĂ”ti maksimaalne suurus on 100 tĂ€hemĂ€rki ja vĂ”ti vĂ”ib sisaldada juhuslikke Unicode koodipunkte, sealhulgas tĂŒhikuid ja muid trĂŒkkimata sĂŒmboleid. Stringide vÀÀrtuste suurus on piiratud 32 768 baitiga ja andmete tehingute maksimaalne vĂ”imalike sisestuste arv on 100. Üldiselt on andmete tehingu maksimaalne suurus umbes 140 KB — viiteks, peaaegu tĂ€pselt Shakespeare'i nĂ€idendi 'Romeo ja Julia' pikkus.”

Loome DAO jÀrgmiste tingimustega:
Kuna startup peab rahastust saama, vajab ta getFunds() toetust vĂ€hemalt 2 osalejalt — DAO investorilt. VĂ€ljastada saab tĂ€pselt nii palju, kui kokku on mĂ€rgitud hÀÀletamisel DAO omanike poolt.

Teeme 3 tĂŒĂŒpi vĂ”tmeid ja lisame tasakaalu haldamiseks loogika 2 uude funktsiooni: vote ja getFunds:
xx
xx_ia = investorid, saadaval saldo (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 uuendama kohe mitu vÀlja:

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

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

Nii see vÀlja nÀeb DAO dApp'i vÔtme-vÀli andmemÀlus, pÀrast seda, kui Bob ja Cooper on tÀiendatud ia-deposiid:
Õppime kirjutama Wavesi nutikaid lepinguid RIDE ja RIDE4DAPPS. Osa 2 (DAO — detsentraliseeritud autonoomne organisatsioon)

Meie sissemakse funktsioon on veidi muutunud:
Õppime kirjutama Wavesi nutikaid lepinguid RIDE ja RIDE4DAPPS. Osa 2 (DAO — detsentraliseeritud autonoomne organisatsioon)

NĂŒĂŒd jĂ”uab kĂ€tte kĂ”ige olulisem hetk DAO tegevuses — hÀÀletamine projektide ĂŒle rahastamiseks.

Bob hÀÀletab projekti Neli poolt 500000 wavelet'i eest:

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

Õppime kirjutama Wavesi nutikaid lepinguid RIDE ja RIDE4DAPPS. Osa 2 (DAO — detsentraliseeritud autonoomne organisatsioon)

Andmehoidlas nÀeme kÔiki vajalikke kirjeid aadressi Neli jaoks:
Õppime kirjutama Wavesi nutikaid lepinguid RIDE ja RIDE4DAPPS. Osa 2 (DAO — detsentraliseeritud autonoomne organisatsioon)
Cooper hÀÀletas ka Neli projekti poolt.
Õppime kirjutama Wavesi nutikaid lepinguid RIDE ja RIDE4DAPPS. Osa 2 (DAO — detsentraliseeritud autonoomne organisatsioon)

Vaatame funktsiooni koodi getFunds. Neli peab koguma vÀhemalt 2 hÀÀlt, et saada vÔimalus vahendeid DAO-st vÀlja vÔtta.
Õppime kirjutama Wavesi nutikaid lepinguid RIDE ja RIDE4DAPPS. Osa 2 (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: []}))

Õppime kirjutama Wavesi nutikaid lepinguid RIDE ja RIDE4DAPPS. Osa 2 (DAO — detsentraliseeritud autonoomne organisatsioon)

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

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

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
Toetuste programmide vÀljakuulutamine

Allikas: habr.com

Osta usaldusvÀÀrne veebihosting DDoS kaitsega, VPS VDS serverid đŸ”„ Osta usaldusvÀÀrne veebihosting DDoS kaitsega, VPS VDS serverid | ProHoster