RIDE va ​​RIDE4DAPPS-da Waves aqlli shartnomalarini yozishni o'rganish. 2-qism (DAO - markazlashtirilmagan avtonom tashkilot)

RIDE va ​​RIDE4DAPPS-da Waves aqlli shartnomalarini yozishni o'rganish. 2-qism (DAO - markazlashtirilmagan avtonom tashkilot)

Hammaga salom!

В birinchisi qismida biz dApp (markazlashtirilmagan dastur) ni qanday yaratish va u bilan ishlashni batafsil ko'rib chiqdik Waves RIDE IDE.

Keling, demontaj qilingan narsalarni biroz sinab ko'raylik misol.

3-bosqich. dApp hisobini sinab ko'rish

RIDE va ​​RIDE4DAPPS-da Waves aqlli shartnomalarini yozishni o'rganish. 2-qism (DAO - markazlashtirilmagan avtonom tashkilot)

Qanday muammolar darhol Elis bilan ovozlarga shoshiladi toza Hisobingiz?
Birinchidan:
Boob va Cooper tasodifan dApp manziliga oddiy dastur yordamida pul yuborishi mumkin uzatish tranzaktsiyalar va shuning uchun ularga qaytib kirish imkoni bo'lmaydi.

Ikkinchisi:
Biz hech qanday tarzda Elisni Boob va/yoki Kuperning roziligisiz pul mablag'larini olishini cheklamaymiz. Tasdiqlashga e'tibor bering, Elisning barcha operatsiyalari amalga oshiriladi.

Keling, Elisni taqiqlash orqali 2 ni tuzatamiz uzatish operatsiyalar. Tuzatilgan skriptni joylashtiring:
RIDE va ​​RIDE4DAPPS-da Waves aqlli shartnomalarini yozishni o'rganish. 2-qism (DAO - markazlashtirilmagan avtonom tashkilot)

Biz dApp Alice va uning imzosi bilan tangalarni yechib olishga harakat qilmoqdamiz. Biz xatoga duch kelamiz:
RIDE va ​​RIDE4DAPPS-da Waves aqlli shartnomalarini yozishni o'rganish. 2-qism (DAO - markazlashtirilmagan avtonom tashkilot)

Olib tashlash orqali olib tashlashga urinish:

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

Skript ishlaydi va biz 2-bandni aniqladik!

4-bosqich. Ovoz berish bilan DAO yarating

Afsuski, RIDE tili hali to'plamlar (lug'atlar, lug'atlar, iteratorlar, reduktorlar va boshqalar) bilan ishlash qobiliyatini ta'minlamaydi. Biroq, tekis kollektsiyalarda har qanday operatsiyalar uchun kalit qiymati biz satrlar bilan, mos ravishda kalitlar va ularning shifrini ochish bilan ishlash tizimini loyihalashimiz mumkin.

Satrlarni birlashtirish juda oson, satrlarni indekslar bilan ajratish mumkin.
Keling, stringni sinov holati sifatida to'playmiz va tahlil qilamiz va bu tranzaksiya natijasiga qanday ta'sir qilishini tekshiramiz.
Biz Elis transfer bitimini imzolay olmasligiga qaror qildik, chunki bu imkoniyat @verifier-da ushbu turdagi tranzaksiya uchun bloklangan edi.

Keling, satrlar bilan mashq qilaylik va keyin buni hal qilaylik.

RIDE satrlari

Tranzaktsiya yana mumkin, biz satrlar bilan qanday ishlashni bilamiz.
RIDE va ​​RIDE4DAPPS-da Waves aqlli shartnomalarini yozishni o'rganish. 2-qism (DAO - markazlashtirilmagan avtonom tashkilot)


Umuman olganda, bizda murakkab mantiqni yozish uchun kerak bo'lgan hamma narsa mavjud DAO dApp.

Ma'lumotlar tranzaksiyalari

Ma'lumotlar tranzaksiyalari:
“Kalitning maksimal oʻlchami 100 ta belgidan iborat boʻlib, kalit oʻzboshimchalik bilan Unicode kod nuqtalarini oʻz ichiga olishi mumkin, shu jumladan boʻshliqlar va boshqa chop etilmaydigan belgilar. String qiymatlari 32,768 100 bayt chegarasiga ega va ma'lumotlar tranzaksiyasida mumkin bo'lgan maksimal yozuvlar soni 140 ni tashkil qiladi. Umuman olganda, ma'lumotlar tranzaksiyasining maksimal hajmi taxminan XNUMX kb - ma'lumot uchun, Shekspirning "Romeo va Juliet" pyesasining deyarli uzunligi. '. ”

Biz quyidagi shartlar bilan DAO yaratamiz:
Boshlang'ich tashkilot qo'ng'iroq qilish orqali mablag' olishi uchun getFunds() kamida 2 ishtirokchi - DAO investorlarining qo'llab-quvvatlashi talab qilinadi. Chiqish ko'rsatilgan summaga to'liq imkon bo'ladi ovoz berish DAO egalari.

Keling, 3 turdagi kalitlarni yarataylik va 2 ta yangi funksiyada balanslar bilan ishlash uchun mantiq qo'shamiz ovoz va getFunds:
xx…xx_ia = investorlar, mavjud balans (ovoz berish, depozit qo'yish, yechib olish)
xx…xx_sv = startaplar, ovozlar soni (ovoz berish, getFunds)
xx…xx_sf = startaplar, ovozlar soni (ovoz berish, getFunds)
xx…xx = umumiy manzil (35 belgi)

Ovoz berishda biz bir vaqtning o'zida bir nechta maydonlarni yangilashimiz kerak edi:

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

WriteSet bizga bir vaqtning o'zida bir nechta yozuvlarni yaratishga imkon beradi invokeScript operatsiyalar.

Bob va Kuper to'ldirilgandan keyin DAO dApp kalit-qiymati do'konida shunday ko'rinadi ia- depozitlar:
RIDE va ​​RIDE4DAPPS-da Waves aqlli shartnomalarini yozishni o'rganish. 2-qism (DAO - markazlashtirilmagan avtonom tashkilot)

Bizning depozit funksiyamiz biroz o'zgardi:
RIDE va ​​RIDE4DAPPS-da Waves aqlli shartnomalarini yozishni o'rganish. 2-qism (DAO - markazlashtirilmagan avtonom tashkilot)

Endi DAO faoliyatidagi eng muhim daqiqa keladi - ovoz berish loyihalarni moliyalashtirish uchun.

Bob Neli loyihasi uchun 500000 XNUMX to'lqinli to'lqinlarda ovoz beradi:

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

RIDE va ​​RIDE4DAPPS-da Waves aqlli shartnomalarini yozishni o'rganish. 2-qism (DAO - markazlashtirilmagan avtonom tashkilot)

Ma'lumotlar do'konida biz Neli manzili uchun barcha kerakli yozuvlarni ko'ramiz:
RIDE va ​​RIDE4DAPPS-da Waves aqlli shartnomalarini yozishni o'rganish. 2-qism (DAO - markazlashtirilmagan avtonom tashkilot)
Kuper ham Neli loyihasiga ovoz berdi.
RIDE va ​​RIDE4DAPPS-da Waves aqlli shartnomalarini yozishni o'rganish. 2-qism (DAO - markazlashtirilmagan avtonom tashkilot)

Keling, funktsiya kodini ko'rib chiqaylik getFunds. Neli DAOdan mablag'ni olib qo'yish uchun kamida 2 ovoz to'plashi kerak.
RIDE va ​​RIDE4DAPPS-da Waves aqlli shartnomalarini yozishni o'rganish. 2-qism (DAO - markazlashtirilmagan avtonom tashkilot)

Neli unga ishonib topshirilgan pulning yarmini qaytarib olmoqchi:

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

RIDE va ​​RIDE4DAPPS-da Waves aqlli shartnomalarini yozishni o'rganish. 2-qism (DAO - markazlashtirilmagan avtonom tashkilot)

U muvaffaqiyatga erishadi, ya'ni DAO ishlaydi!

Biz tilda DAO yaratish jarayonini ko'rib chiqdik RIDE4DAPPS.
Keyingi qismlarda biz kodni qayta tiklash va keys testini batafsil ko'rib chiqamiz.

To'liq kod 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
    }
}

Birinchi qism
Github uchun kod
Waves RIDE IDE
Grant dasturi haqida e'lon

Manba: www.habr.com

a Izoh qo'shish