آموزش نوشتن قراردادهای هوشمند Waves در RIDE و RIDE4DAPPS. بخش 2 (DAO - سازمان غیرمتمرکز خودمختار)

آموزش نوشتن قراردادهای هوشمند Waves در RIDE و RIDE4DAPPS. بخش 2 (DAO - سازمان غیرمتمرکز خودمختار)

خوش آمدید!

В اول بخش ما به طور مفصل به نحوه ایجاد و کار با dApp (برنامه غیرمتمرکز) در آن نگاه کردیم امواج RIDE IDE.

حالا بیایید قطعه جدا شده را کمی تست کنیم مثال.

مرحله 3. آزمایش حساب dApp

آموزش نوشتن قراردادهای هوشمند Waves در RIDE و RIDE4DAPPS. بخش 2 (DAO - سازمان غیرمتمرکز خودمختار)

چه مشکلاتی بلافاصله با آلیس به سراغ شما می آید؟ شیک حساب؟
اول:
Boob و Cooper ممکن است به طور تصادفی وجوهی را با استفاده از معمولی به آدرس dApp ارسال کنند انتقال تراکنش ها و در نتیجه قادر به دسترسی مجدد به آنها نخواهید بود.

دوم:
ما آلیس را به هیچ وجه از برداشت وجه بدون تایید Boob و/یا Cooper محدود نمی کنیم. از آنجایی که به تایید دقت کنید، تمام تراکنش‌های آلیس اجرا می‌شوند.

بیایید دومی را با ممنوع کردن آلیس درست کنیم انتقال معاملات بیایید اسکریپت اصلاح شده را مستقر کنیم:
آموزش نوشتن قراردادهای هوشمند Waves در RIDE و RIDE4DAPPS. بخش 2 (DAO - سازمان غیرمتمرکز خودمختار)

ما در حال تلاش برای برداشت سکه ها از dApp Alice و امضای او هستیم. یک خطا دریافت می کنیم:
آموزش نوشتن قراردادهای هوشمند Waves در RIDE و RIDE4DAPPS. بخش 2 (DAO - سازمان غیرمتمرکز خودمختار)

بیایید سعی کنیم از طریق برداشت برداشت کنیم:

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

فیلمنامه کار می کند و ما به نکته دوم پی بردیم!

مرحله 4. با رای دادن یک DAO ایجاد کنید

متأسفانه زبان RIDE هنوز توانایی کار با مجموعه ها (فرهنگ لغت نامه ها، تکرار کننده ها، کاهش دهنده ها و غیره) را فراهم نمی کند. با این حال، برای هر عملیات با مجموعه های مسطح ارزش کلیدی می‌توانیم سیستمی برای کار با رشته‌ها، بر اساس کلیدها و رمزگشایی آنها طراحی کنیم.

به هم پیوستن رشته ها بسیار آسان است؛ رشته ها را می توان با نمایه ها از هم جدا کرد.
بیایید یک رشته را به عنوان نمونه آزمایشی جمع آوری و تجزیه کنیم و بررسی کنیم که چگونه این امر بر نتیجه تراکنش تأثیر می گذارد.
ما به این واقعیت رسیدیم که آلیس نمی تواند تراکنش Transfer را امضا کند، زیرا این توانایی در @verifier برای این نوع تراکنش مسدود شده است.

بیایید با رشته ها تمرین کنیم و سپس آن را حل کنیم.

سوار رشته ها

معامله دوباره امکان پذیر است، ما می دانیم که چگونه با رشته ها کار کنیم.
آموزش نوشتن قراردادهای هوشمند Waves در RIDE و RIDE4DAPPS. بخش 2 (DAO - سازمان غیرمتمرکز خودمختار)


در کل، ما همه چیز لازم برای نوشتن منطق پیچیده را داریم DAO dApp.

تراکنش های داده

تراکنش های داده:
حداکثر اندازه برای یک کلید 100 کاراکتر است و یک کلید می تواند حاوی نقاط کد دلخواه یونیکد از جمله فاصله ها و سایر نمادهای غیر قابل چاپ باشد. مقادیر رشته دارای محدودیت 32,768 بایت هستند و حداکثر تعداد ورودی های ممکن در تراکنش داده ها 100 است. به طور کلی، حداکثر اندازه یک تراکنش داده حدود 140 کیلوبایت است - برای مرجع، تقریباً دقیقاً طول نمایشنامه شکسپیر "رومئو و ژولیت" '."

ما یک DAO با شرایط زیر ایجاد می کنیم:
برای اینکه یک استارتاپ با تماس تلفنی بودجه دریافت کند getFunds() حمایت حداقل 2 شرکت کننده - سرمایه گذاران DAO - مورد نیاز است. برداشت دقیقاً به اندازه کل نشان داده شده در آن امکان پذیر خواهد بود رای دادن صاحبان DAO

بیایید 3 نوع کلید بسازیم و منطق کار با تعادل را در 2 تابع جدید vote و getFunds اضافه کنیم:
xx…xx_ia = سرمایه گذاران، موجودی موجود (رای، واریز، برداشت)
xx…xx_sv = استارت آپ ها، تعداد رای ها (رای دادن، دریافت وجوه)
xx…xx_sf = استارت آپ ها، تعداد رای ها (رای دادن، دریافت وجوه)
xx…xx = آدرس عمومی (35 کاراکتر)

لطفاً توجه داشته باشید که در Vote باید چندین فیلد را همزمان به روز کنیم:

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

WriteSet به ما این امکان را می دهد که چندین رکورد را در یک زمان ایجاد کنیم invokeScript معاملات

پس از تکمیل مجدد باب و کوپر، در حافظه کلیدی DAO dApp به این شکل به نظر می رسد. ia-سپرده ها:
آموزش نوشتن قراردادهای هوشمند Waves در RIDE و RIDE4DAPPS. بخش 2 (DAO - سازمان غیرمتمرکز خودمختار)

تابع سپرده ما کمی تغییر کرده است:
آموزش نوشتن قراردادهای هوشمند Waves در RIDE و RIDE4DAPPS. بخش 2 (DAO - سازمان غیرمتمرکز خودمختار)

اکنون مهمترین لحظه در فعالیت های DAO فرا می رسد - رای برای پروژه هایی که باید تامین مالی شوند.

رای باب به پروژه 500000 موجک نلی:

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

آموزش نوشتن قراردادهای هوشمند Waves در RIDE و RIDE4DAPPS. بخش 2 (DAO - سازمان غیرمتمرکز خودمختار)

در فروشگاه داده، تمام ورودی های لازم برای آدرس نلی را می بینیم:
آموزش نوشتن قراردادهای هوشمند Waves در RIDE و RIDE4DAPPS. بخش 2 (DAO - سازمان غیرمتمرکز خودمختار)
کوپر همچنین به پروژه نلی رای داد.
آموزش نوشتن قراردادهای هوشمند Waves در RIDE و RIDE4DAPPS. بخش 2 (DAO - سازمان غیرمتمرکز خودمختار)

بیایید نگاهی به کد تابع بیاندازیم getFunds. Neli باید حداقل 2 رای جمع آوری کند تا بتواند وجوه خود را از DAO برداشت کند.
آموزش نوشتن قراردادهای هوشمند Waves در RIDE و RIDE4DAPPS. بخش 2 (DAO - سازمان غیرمتمرکز خودمختار)

نلی قرار است نیمی از مبلغی را که به او سپرده شده است پس بگیرد:

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

آموزش نوشتن قراردادهای هوشمند Waves در RIDE و RIDE4DAPPS. بخش 2 (DAO - سازمان غیرمتمرکز خودمختار)

او موفق می شود، یعنی DAO کار می کند!

ما به روند ایجاد DAO در زبان نگاه کردیم RIDE4DAPPS.
در قسمت‌های بعدی نگاهی دقیق‌تر به بازسازی کد و تست موارد خواهیم داشت.

نسخه کامل کد در 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
    }
}

بخش اول
کد در GitHub
امواج RIDE IDE
اطلاعیه برنامه کمک هزینه

منبع: www.habr.com

اضافه کردن نظر