Dysgu ysgrifennu contractau smart Waves ar RIDE a RIDE4DAPPS. Rhan 2 (DAO - Sefydliad Ymreolaethol Datganoledig)

Dysgu ysgrifennu contractau smart Waves ar RIDE a RIDE4DAPPS. Rhan 2 (DAO - Sefydliad Ymreolaethol Datganoledig)

Helo bawb!

В y cyntaf rhan edrychwyd yn fanwl ar sut i greu a gweithio gyda dApp (cymhwysiad datganoledig) i mewn Tonnau RIDE IDE.

Gadewch i ni brofi'r un sydd wedi'i ddadosod ychydig nawr enghraifft.

Cam 3. Profi'r cyfrif dApp

Dysgu ysgrifennu contractau smart Waves ar RIDE a RIDE4DAPPS. Rhan 2 (DAO - Sefydliad Ymreolaethol Datganoledig)

Pa broblemau sy'n neidio allan atoch chi ar unwaith gydag Alice? dApp Cyfrif?
Yn gyntaf:
Gall Boob a Cooper anfon arian yn ddamweiniol i'r cyfeiriad dApp gan ddefnyddio rheolaidd trosglwyddo trafodion ac felly ni fydd yn gallu cael mynediad iddynt yn ôl.

Yn ail:
Nid ydym yn cyfyngu Alice mewn unrhyw ffordd rhag tynnu arian yn ôl heb gymeradwyaeth Boob a/neu Cooper. Gan fod, rhowch sylw i wirio, bydd yr holl drafodion gan Alice yn cael eu gweithredu.

Gadewch i ni drwsio 2il trwy wahardd Alice trosglwyddo trafodion. Gadewch i ni ddefnyddio'r sgript wedi'i chywiro:
Dysgu ysgrifennu contractau smart Waves ar RIDE a RIDE4DAPPS. Rhan 2 (DAO - Sefydliad Ymreolaethol Datganoledig)

Rydym yn ceisio tynnu darnau arian o dApp Alice a'i llofnod. Rydym yn cael gwall:
Dysgu ysgrifennu contractau smart Waves ar RIDE a RIDE4DAPPS. Rhan 2 (DAO - Sefydliad Ymreolaethol Datganoledig)

Gadewch i ni geisio tynnu'n ôl trwy dynnu'n ôl:

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

Mae'r sgript yn gweithio ac fe wnaethom gyfrifo'r 2il bwynt!

Cam 4. Creu DAO gyda phleidleisio

Yn anffodus, nid yw'r iaith RIDE eto'n darparu'r gallu i weithio gyda chasgliadau (geiriaduron, iterwyr, gostyngwyr, ac ati). Fodd bynnag, ar gyfer unrhyw weithrediadau gyda chasgliadau fflat gwerth allweddol gallwn ddylunio system ar gyfer gweithio gyda llinynnau, yn unol â hynny gydag allweddi a'u dadgryptio.

Mae llinynnau'n hawdd iawn i'w cydgadwynu; gall llinynnau gael eu gwahanu gan fynegeion.
Gadewch i ni gasglu a dosrannu llinyn fel enghraifft brawf a gwirio sut mae hyn yn effeithio ar ganlyniad y trafodiad.
Fe wnaethom setlo ar y ffaith na allai Alice lofnodi'r trafodiad Trosglwyddo, gan fod y gallu hwn wedi'i rwystro yn @verifier ar gyfer y math hwn o drafodiad.

Gadewch i ni ymarfer gyda llinynnau ac yna datrys hyn.

Llinynnau RIDE

Mae'r trafodiad yn bosibl eto, rydym yn gwybod sut i weithio gyda llinynnau.
Dysgu ysgrifennu contractau smart Waves ar RIDE a RIDE4DAPPS. Rhan 2 (DAO - Sefydliad Ymreolaethol Datganoledig)


Yn gyfan gwbl, mae gennym bopeth sydd ei angen i ysgrifennu rhesymeg gymhleth DAO dApp.

Trafodion Data

Trafodion Data:
“Y maint mwyaf ar gyfer allwedd yw 100 nod, a gall allwedd gynnwys pwyntiau cod Unicode mympwyol gan gynnwys bylchau a symbolau eraill na ellir eu hargraffu. Mae gan werthoedd llinynnau derfyn o 32,768 beit ac uchafswm nifer y cofnodion posibl mewn trafodiad data yw 100. Yn gyffredinol, maint mwyaf trafodiad data yw tua 140kb — er gwybodaeth, bron yn union hyd drama Shakespeare 'Romeo and Juliet '.”

Rydym yn creu DAO gyda'r amodau canlynol:
Er mwyn i gwmni newydd dderbyn cyllid trwy ffonio caelFunds() mae angen cefnogaeth o leiaf 2 gyfranogwr - buddsoddwyr DAO. Tynnu'n ôl bydd yn bosibl yn union cymaint â'r cyfanswm a nodir ar pleidleisio Perchnogion DAO.

Gadewch i ni wneud 3 math o allwedd ac ychwanegu rhesymeg ar gyfer gweithio gyda balansau mewn 2 swyddogaeth newydd, pleidlais a getFunds:
xx…xx_ia = buddsoddwyr, balans sydd ar gael (pleidlais, blaendal, tynnu'n ôl)
xx…xx_sv = cychwyniadau, nifer y pleidleisiau (pleidlais, getFunds)
xx…xx_sf = cychwyniadau, nifer y pleidleisiau (pleidlais, getFunds)
xx…xx = cyfeiriad cyhoeddus (35 nod)

Sylwch fod angen i ni ddiweddaru sawl maes ar unwaith yn y Bleidlais:

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

Mae WriteSet yn ein galluogi i wneud sawl cofnod ar unwaith o fewn un invokeScript trafodion.

Dyma sut mae'n edrych yn storfa gwerth allweddol y DAO dApp, ar ôl i Bob a Cooper ailgyflenwi ia- adneuon:
Dysgu ysgrifennu contractau smart Waves ar RIDE a RIDE4DAPPS. Rhan 2 (DAO - Sefydliad Ymreolaethol Datganoledig)

Mae ein swyddogaeth adneuo wedi newid ychydig:
Dysgu ysgrifennu contractau smart Waves ar RIDE a RIDE4DAPPS. Rhan 2 (DAO - Sefydliad Ymreolaethol Datganoledig)

Nawr daw'r foment bwysicaf yng ngweithgareddau'r DAO - pleidleisio i brosiectau gael eu hariannu.

Bob yn pleidleisio dros brosiect 500000 o donfeddi Neli:

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

Dysgu ysgrifennu contractau smart Waves ar RIDE a RIDE4DAPPS. Rhan 2 (DAO - Sefydliad Ymreolaethol Datganoledig)

Yn y storfa ddata gwelwn yr holl gofnodion angenrheidiol ar gyfer cyfeiriad Neli:
Dysgu ysgrifennu contractau smart Waves ar RIDE a RIDE4DAPPS. Rhan 2 (DAO - Sefydliad Ymreolaethol Datganoledig)
Pleidleisiodd Cooper hefyd dros brosiect Neli.
Dysgu ysgrifennu contractau smart Waves ar RIDE a RIDE4DAPPS. Rhan 2 (DAO - Sefydliad Ymreolaethol Datganoledig)

Gadewch i ni edrych ar y cod swyddogaeth caelFunds. Rhaid i Neli gasglu o leiaf 2 bleidlais i allu tynnu arian o'r DAO.
Dysgu ysgrifennu contractau smart Waves ar RIDE a RIDE4DAPPS. Rhan 2 (DAO - Sefydliad Ymreolaethol Datganoledig)

Mae Neli yn mynd i dynnu hanner y swm a ymddiriedwyd iddi:

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

Dysgu ysgrifennu contractau smart Waves ar RIDE a RIDE4DAPPS. Rhan 2 (DAO - Sefydliad Ymreolaethol Datganoledig)

Mae hi'n llwyddo, hynny yw, mae DAO yn gweithio!

Edrychon ni ar y broses o greu DAO yn yr iaith RIDE4DAPPS.
Yn y rhannau canlynol byddwn yn edrych yn agosach ar ailffactorio cod a phrofi achosion.

Fersiwn llawn o'r cod yn Tonnau 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
    }
}

Rhan gyntaf
Cod ar GitHub
Tonnau RIDE IDE
Cyhoeddi'r rhaglen grantiau

Ffynhonnell: hab.com

Ychwanegu sylw