Saluton ĉiuj!
В
Ni provu nun la malmuntitan
Etapo 3. Provante la konton dApp
Kiuj problemoj tuj saltas al vi kun Alico? dApp Konto?
Unue:
Boob kaj Cooper eble hazarde sendas financon al la dApp-adreso uzante regulan transigo transakcioj kaj tiel ne povos aliri ilin reen.Due:
Ni neniel limigas Alicion retiri financon sen la aprobo de Boob kaj/aŭ Cooper. Ĉar, atentu kontroli, ĉiuj transakcioj de Alice estos efektivigitaj.
Ni riparu 2-a per malpermeso de Alicio transigo transakcioj. Ni disfaldu la korektitan skripton:

Ni provas retiri monerojn de dApp Alice kaj ŝia subskribo. Ni ricevas eraron:
Ni provu retiriĝi per retiro:
broadcast(invokeScript({dappAddress: address(env.accounts[1]), call:{function:"withdraw",args:[{type:"integer", value: 1000000}]}, payment: []}))
La skripto funkcias kaj ni eltrovis la 2-an punkton!
Etapo 4. Kreu DAO kun voĉdonado
Bedaŭrinde, la RIDE-lingvo ankoraŭ ne disponigas la kapablon labori kun kolektoj (vortaroj, iteratoroj, reduktiloj ktp.). Tamen, por iuj operacioj kun plataj kolektoj ŝlosila valoro ni povas desegni sistemon por labori kun ŝnuroj, laŭe kun ŝlosiloj kaj ilia malĉifrado.
Ŝnuroj estas tre facile kunleblaj; ĉenoj povas esti apartigitaj per indeksoj.
Ni kolektu kaj analizu ĉenon kiel prova ekzemplo kaj kontrolu kiel tio influas la rezulton de la transakcio.
Ni decidis pri tio, ke Alice ne povis subskribi la Transakcion de Transdono, ĉar ĉi tiu kapablo estis blokita en @verifier por ĉi tiu tipo de transakcio.
Ni ekzercu per ŝnuroj kaj poste solvu ĉi tion.
RIDE Kordoj
La transakcio denove eblas, ni scias kiel labori kun ŝnuroj.

Entute ni havas ĉion necesan por skribi kompleksan logikon DAO dApp.
Datumaj Transakcioj
Datumaj Transakcioj:
"La maksimuma grandeco por ŝlosilo estas 100 signoj, kaj ŝlosilo povas enhavi arbitrajn Unikodajn kodpunktojn inkluzive de spacoj kaj aliaj nepreseblaj simboloj. Ŝnuraj valoroj havas limon de 32,768 100 bajtoj kaj la maksimuma nombro da eblaj eniroj en datumtransakcio estas 140. Ĝenerale, la maksimuma grandeco de datumtransakcio estas ĉirkaŭ XNUMXkb - por referenco, preskaŭ ĝuste la longeco de la teatraĵo de Ŝekspiro "Romeo kaj Julieta". '."
Ni kreas DAO kun la sekvaj kondiĉoj:
Por ke noventrepreno ricevu financadon per vokado getFunds() la subteno de almenaŭ 2 partoprenantoj - DAO-investantoj - estas bezonata. Retiriĝi ĝi eblos ĝuste tiom kiom la sumo indikita sur balotado DAO-posedantoj.
Ni faru 3 specojn de ŝlosiloj kaj aldonu logikon por labori kun saldo en 2 novaj funkcioj voĉdoni kaj getFunds:
xx...xx_ia = investantoj, disponebla saldo (voĉdono, deponejo, retiro)
xx...xx_sv = noventreprenoj, nombro da voĉoj (voĉdoni, akiriFundojn)
xx...xx_sf = noventreprenoj, nombro da voĉoj (voĉdoni, akiriFundojn)
xx...xx = publika adreso (35 signoj)
Bonvolu noti, ke en Voĉdono ni devis ĝisdatigi plurajn kampojn samtempe:
WriteSet([DataEntry(key1, value1), DataEntry(key2, value2)]),
WriteSet permesas al ni fari plurajn rekordojn samtempe ene de unu invokeScript transakcioj.
Jen kiel ĝi aspektas en la ŝlosilvalora stokado de la DAO dApp, post kiam Bob kaj Cooper replenigis ia-deponejoj:
Nia depona funkcio iomete ŝanĝiĝis:
Nun venas la plej grava momento en la agadoj de la DAO - voĉdoni por projektoj financataj.
Bob voĉdonas por la projekto de 500000 ondetoj de Neli:
broadcast(invokeScript({dappAddress: address(env.accounts[1]), call:{function:"vote",args:[{type:"integer", value: 500000}, {type:"string", value: "3MrXEKJr9nDLNyVZ1d12Mq4jjeUYwxNjMsH"}]}, payment: []}))
En la datumvendejo ni vidas ĉiujn necesajn enskribojn por la adreso de Neli:
Cooper ankaŭ voĉdonis por la Neli-projekto.
Ni rigardu la funkciokodon getFunds. Neli devas kolekti minimume 2 voĉojn por povi eltiri financon de la DAO.
Neli retiros duonon de la sumo konfidita al ŝi:
broadcast(invokeScript({dappAddress: address(env.accounts[1]), call:{function:"getFunds",args:[{type:"integer", value: 500000}]}, payment: []}))
Ŝi sukcesas, tio estas, DAO funkcias!
Ni rigardis la procezon de kreado de DAO en la lingvo RIDE4DAPPS.
En la sekvaj partoj ni pli detale rigardos kodan refaktoradon kaj kaztestadon.
Plena versio de la kodo en
# 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
}
}
fonto: www.habr.com