Hello everyone!
В
Litte wy de útinoarte no in bytsje testje
Stage 3. It testen fan it dApp-akkount
Hokker problemen springe jo fuortendaliks út mei Alice? dApp Rekken?
Earst:
Boob en Cooper meie per ongeluk fûnsen stjoere nei it dApp-adres mei gewoane oerdracht transaksjes en dus net by steat wêze om tagong ta harren werom.Twad:
Wy beheine Alice net op ien of oare manier fan it weromlûken fan fûnsen sûnder de goedkarring fan Boob en / of Cooper. Sûnt, betelje omtinken foar ferifiearjen, sille alle transaksjes fan Alice wurde útfierd.
Litte wy 2e reparearje troch Alice te ferbieden oerdracht transaksjes. Litte wy it korrizjearre skript ynsette:

Wy besykje munten werom te lûken fan dApp Alice en har hantekening. Wy krije in flater:
Litte wy besykje werom te lûken fia weromlûken:
broadcast(invokeScript({dappAddress: address(env.accounts[1]), call:{function:"withdraw",args:[{type:"integer", value: 1000000}]}, payment: []}))
It skript wurket en wy hawwe it 2e punt útfûn!
Stage 4. Meitsje in DAO mei stimmen
Spitigernôch biedt de RIDE-taal noch net de mooglikheid om mei kolleksjes te wurkjen (wurdboekwurdboeken, iterators, ferlytsers, ensfh.). Lykwols, foar alle operaasjes mei platte kolleksjes kaai-wearde wy kinne in systeem ûntwerpe foar it wurkjen mei snaren, neffens toetsen en har ûntsiferje.
Stringen binne heul maklik te ferbinen; snaren kinne wurde skieden troch yndeksen.
Litte wy in tekenrige sammelje en analysearje as testfoarbyld en kontrolearje hoe't dit de útkomst fan 'e transaksje beynfloedet.
Wy hawwe fêstlein oer it feit dat Alice de Transfer-transaksje net koe ûndertekenje, om't dizze mooglikheid waard blokkearre yn @verifier foar dit soarte transaksje.
Litte wy oefenje mei snaren en dan oplosse dit.
RIDE Strings
De transaksje is mooglik wer, wy witte hoe te wurkjen mei snaren.

Yn totaal hawwe wy alles nedich om komplekse logika te skriuwen DAO dApp.
Data Transaksjes
Gegevenstransaksjes:
"De maksimale grutte foar in kaai is 100 tekens, en in kaai kin willekeurige Unicode-koadepunten befetsje, ynklusyf spaasjes en oare net-printbere symboalen. Stringwearden hawwe in limyt fan 32,768 bytes en it maksimum oantal mooglike yngongen yn gegevenstransaksjes is 100. Oer it algemien is de maksimale grutte fan in gegevenstransaksje sawat 140kb - foar referinsje, hast krekt de lingte fan Shakespeare's toanielstik 'Romeo en Julia' '."
Wy meitsje in DAO mei de folgjende betingsten:
Om in startup te ûntfangen finansiering troch te skiljen getFunds() de stipe fan op syn minst 2 dielnimmers - DAO ynvestearders - is nedich. Ôfdraaie it sil mooglik wêze krekt safolle as it totaal oanjûn op stimme DAO eigners.
Litte wy 3 soarten toetsen meitsje en logika tafoegje foar it wurkjen mei saldo's yn 2 nije funksjes stimme en getFunds:
xx…xx_ia = ynvestearders, beskikber lykwicht (stim, boarch, weromlûken)
xx…xx_sv = startups, oantal stimmen (stim, getFunds)
xx…xx_sf = startups, oantal stimmen (stim, getFunds)
xx…xx = iepenbier adres (35 tekens)
Tink derom dat wy yn 'e stimming ferskate fjilden tagelyk moasten bywurkje:
WriteSet([DataEntry(key1, value1), DataEntry(key2, value2)]),
WriteSet lit ús ferskate records tagelyk binnen ien meitsje invokeScript transaksjes.
Dit is hoe't it liket yn 'e kaai-wearde opslach fan' e DAO dApp, neidat Bob en Cooper oanfolle ia- ôfsettings:
Us boarchfunksje is wat feroare:
No komt it wichtichste momint yn 'e aktiviteiten fan' e DAO - stim foar projekten dy't finansierd wurde.
Bob stimt foar Neli's 500000 wavelets-projekt:
broadcast(invokeScript({dappAddress: address(env.accounts[1]), call:{function:"vote",args:[{type:"integer", value: 500000}, {type:"string", value: "3MrXEKJr9nDLNyVZ1d12Mq4jjeUYwxNjMsH"}]}, payment: []}))
Yn 'e gegevenswinkel sjogge wy alle nedige yngongen foar Neli's adres:
Cooper stimde ek foar it Neli-projekt.
Litte we ris nei de funksje koade getFunds. Neli moat in minimum fan 2 stimmen sammelje om jild út de DAO werom te heljen.
Neli sil de helte fan it oan har tawiisde bedrach weromlûke:
broadcast(invokeScript({dappAddress: address(env.accounts[1]), call:{function:"getFunds",args:[{type:"integer", value: 500000}]}, payment: []}))
Se slagget, dat is, DAO wurket!
Wy seagen nei it proses fan it meitsjen fan in DAO yn 'e taal RIDE4DAPPS.
Yn 'e folgjende dielen sille wy in tichterby besjen op koade refactoring en case-testen.
Folsleine ferzje fan de koade yn
# 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
}
}
Boarne: www.habr.com