Սովորում ենք գրել Waves խելացի պայմանագրեր RIDE-ի և RIDE4DAPPS-ի վրա: Մաս 2 (DAO - Ապակենտրոնացված ինքնավար կազմակերպություն)

Սովորում ենք գրել Waves խելացի պայմանագրեր RIDE-ի և RIDE4DAPPS-ի վրա: Մաս 2 (DAO - Ապակենտրոնացված ինքնավար կազմակերպություն)

Hello everyone!

В առաջինը Այս մասում մենք մանրամասնորեն քննարկեցինք, թե ինչպես ստեղծել և աշխատել dApp (ապակենտրոնացված ծրագիր)-ի հետ։ Waves Ride IDE.

Եկեք մի փոքր փորձարկենք ապամոնտաժվածը հիմա օրինակ.

Քայլ 3. dApp հաշվի փորձարկում

Սովորում ենք գրել Waves խելացի պայմանագրեր RIDE-ի և RIDE4DAPPS-ի վրա: Մաս 2 (DAO - Ապակենտրոնացված ինքնավար կազմակերպություն)

Ի՞նչ խնդիրներ են անմիջապես գրավում Ալիսի ուշադրությունը դԱՊ Հաշիվ?
Առաջին
Բուբը և Քուփերը կարող են պատահաբար գումար ուղարկել dApp հասցեին՝ օգտագործելով սովորական փոխանցել գործարքները և, հետևաբար, դրանց հետադարձ հասանելիություն չի լինի։

Երկրորդ `
Մենք որևէ կերպ չենք սահմանափակում Ալիսին Բուբի կամ (և) Քուփերի համաձայնության բացակայության դեպքում միջոցներ դուրս բերելու հարցում։ Քանի որ, ուշադրություն դարձրեք ստուգմանը, Ալիսի բոլոր գործարքները կկատարվեն։

Եկեք շտկենք երկրորդը՝ արգելափակելով Ալիսին։ փոխանցել գործարքներ։ Տեղակայեք ուղղված սկրիպտը։
Սովորում ենք գրել 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: []}))

Սցենարը աշխատում է, և մենք լուծեցինք 2-րդ կետը։

Քայլ 4. Ստեղծեք DAO քվեարկությամբ

Դժբախտաբար, RIDE լեզուն դեռևս չի ապահովում հավաքածուների հետ աշխատելու հնարավորություն (բառարանների բառարաններ, իտերատորներ, ռեդուկտորներ և այլն): Այնուամենայնիվ, հարթ հավաքածուների հետ ցանկացած գործողության համար բանալի-արժեք Մենք կարող ենք նախագծել տողերի հետ աշխատելու համակարգ, համապատասխանաբար՝ բանալիների և դրանց վերծանման հետ։

Տողերը շատ հեշտ է միացնել, տողերը կարելի է բաժանել ինդեքսների։
Եկեք հավաքենք և ապամոնտաժենք տողը որպես փորձարկման օրինակ և ստուգենք, թե ինչպես է դա ազդում գործարքի արդյունքի վրա։
Արդյունքում Ալիսը չկարողացավ ստորագրել փոխանցման գործարքը, քանի որ այս հնարավորությունը արգելափակված էր @verifier-ում այս տեսակի գործարքի համար։

Եկեք մարզվենք լարերի հետ, ապա լուծենք սա։

RIDE լարեր

Գործարքը կրկին հնարավոր է, մենք գիտենք, թե ինչպես աշխատել տողերի հետ։
Սովորում ենք գրել Waves խելացի պայմանագրեր RIDE-ի և RIDE4DAPPS-ի վրա: Մաս 2 (DAO - Ապակենտրոնացված ինքնավար կազմակերպություն)


Այսպիսով, մենք ունենք ամեն ինչ, ինչ անհրաժեշտ է բարդ տրամաբանություն գրելու համար։ DAO dApp.

Տվյալների գործարքներ

Տվյալների գործարքներ՝
«Բանալու առավելագույն չափը 100 նիշ է, և բանալին կարող է պարունակել Unicode կոդի կամայական կետեր, ներառյալ բացատներ և այլ ոչ տպելի նշաններ: Տողային արժեքների սահմանափակումը 32,768 բայթ է, իսկ տվյալների գործարքում հնարավոր գրառումների առավելագույն քանակը՝ 100: Ընդհանուր առմամբ, տվյալների գործարքի առավելագույն չափը մոտ 140 կբ է՝ համեմատության համար, գրեթե ճիշտ այնքան, որքան Շեքսպիրի «Ռոմեո և Ջուլիետ» պիեսի երկարությունն է»:

Մենք ստեղծում ենք DAO հետևյալ պայմաններով՝
Որպեսզի ստարտափը ֆինանսավորում ստանա՝ զանգահարելով ստանալ միջոցներ() Պահանջվում է առնվազն 2 մասնակցի՝ DAO ներդրողների աջակցությունը։ Վերցրեք հնարավոր կլինի ունենալ ճիշտ այնքան, որքան նշված է ընդհանուրը քվեարկություն DAO-ի սեփականատերեր։

Եկեք ստեղծենք 3 տեսակի բանալի և ավելացնենք տրամաբանություն մնացորդների հետ աշխատելու համար 2 նոր ֆունկցիաներում՝ vote և getFunds։
xx…xx_իա = ներդրողներ, հասանելի մնացորդ (քվեարկություն, ավանդ, հետ վերցնել)
xx…xx_sv = ստարտափներ, ձայների քանակ (քվեարկեք, ստացեք միջոցներ)
xx…xx_sf = ստարտափներ, ձայների քանակ (քվեարկեք, ստացեք միջոցներ)
xx…xx = հանրային հասցե (35 նիշ)

Նկատի ունեցեք, որ «Քվեարկություն» բաժնում մենք պետք է միաժամանակ մի քանի դաշտ թարմացնեինք։

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 - Ապակենտրոնացված ինքնավար կազմակերպություն)

Եկեք նայենք ֆունկցիայի կոդին ստանալ միջոցներՆելին պետք է հավաքի առնվազն 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-ում
Waves Ride IDE
Դրամաշնորհային ծրագրի հայտարարություն

Source: www.habr.com

Գնեք հուսալի հոստինգ DDoS պաշտպանությամբ կայքերի, VPS VDS սերվերների համար 🔥 Գնեք հուսալի կայքերի հոսթինգ՝ DDoS պաշտպանությամբ, VPS VDS սերվերներով | ProHoster