Përshëndetje të gjithëve!
В
Le të testojmë pak tani atë të çmontuar
Faza 3. Testimi i llogarisë dApp
Çfarë problemesh ju lindin menjëherë me Alice? DAPP Llogari?
Во-первых:
Boob dhe Cooper mund të dërgojnë aksidentalisht fonde në adresën dApp duke përdorur të rregullt transferuar transaksionet dhe kështu nuk do të jetë në gjendje t'i qaset përsëri.Во-вторых:
Ne nuk e kufizojmë në asnjë mënyrë Alice nga tërheqja e fondeve pa miratimin e Boob dhe/ose Cooper. Meqenëse, kushtojini vëmendje verifikimit, të gjitha transaksionet nga Alice do të ekzekutohen.
Le të rregullojmë të dytën duke e ndaluar Alice transferuar transaksionet. Le të vendosim skriptin e korrigjuar:

Ne po përpiqemi të tërheqim monedha nga dApp Alice dhe nënshkrimi i saj. Ne marrim një gabim:
Le të përpiqemi të tërhiqemi përmes tërheqjes:
broadcast(invokeScript({dappAddress: address(env.accounts[1]), call:{function:"withdraw",args:[{type:"integer", value: 1000000}]}, payment: []}))
Skenari funksionon dhe ne kuptuam pikën e dytë!
Faza 4. Krijo një DAO me votim
Fatkeqësisht, gjuha RIDE nuk ofron ende aftësinë për të punuar me koleksione (fjalorë fjalorë, përsëritës, reduktues, etj.). Megjithatë, për çdo operacion me koleksione të sheshta vlera kryesore ne mund të dizajnojmë një sistem për të punuar me vargje, në përputhje me rrethanat me çelësat dhe deshifrimin e tyre.
Vargjet janë shumë të lehta për t'u lidhur; vargjet mund të ndahen me indekse.
Le të mbledhim dhe analizojmë një varg si një shembull testimi dhe të kontrollojmë se si kjo ndikon në rezultatin e transaksionit.
Ne u vendosëm për faktin se Alice nuk mund të nënshkruante transaksionin e Transferimit, pasi kjo aftësi u bllokua në @verifier për këtë lloj transaksioni.
Le të praktikojmë me vargje dhe më pas ta zgjidhim këtë.
RIDE Strings
Transaksioni është i mundur përsëri, ne dimë të punojmë me vargje.

Në total, ne kemi gjithçka të nevojshme për të shkruar logjikë komplekse DAO dApp.
Transaksionet e të dhënave
Transaksionet e të dhënave:
"Madhësia maksimale për një çelës është 100 karaktere dhe një çelës mund të përmbajë pika arbitrare të kodit të Unicode duke përfshirë hapësira dhe simbole të tjera jo të printueshme. Vlerat e vargut kanë një kufi prej 32,768 byte dhe numri maksimal i hyrjeve të mundshme në transaksionin e të dhënave është 100. Në përgjithësi, madhësia maksimale e një transaksioni të dhënash është rreth 140 kb - për referencë, pothuajse saktësisht gjatësia e shfaqjes së Shekspirit 'Romeo dhe Zhulieta '."
Ne krijojmë një DAO me kushtet e mëposhtme:
Në mënyrë që një startup të marrë fonde duke telefonuar getFunds () kërkohet mbështetja e të paktën 2 pjesëmarrësve - investitorë DAO. Të tërheqë do të jetë e mundur saktësisht aq sa është treguar totali votimi Pronarët e DAO.
Le të bëjmë 3 lloje çelësash dhe të shtojmë logjikën për të punuar me bilancet në 2 funksione të reja votoni dhe merrni fonde:
xx…xx_ia = investitorët, bilanci i disponueshëm (votim, depozitë, tërheqje)
xx…xx_sv = startups, numri i votave (votoni, merrni fonde)
xx…xx_sf = startups, numri i votave (votoni, merrni fonde)
xx…xx = adresë publike (35 karaktere)
Ju lutemi vini re se në Vote na është dashur të përditësojmë disa fusha njëherësh:
WriteSet([DataEntry(key1, value1), DataEntry(key2, value2)]),
WriteSet na lejon të bëjmë disa regjistrime njëherësh brenda një invokeScript transaksionet.
Kështu duket në hapësirën ruajtëse të vlerës së çelësit të DAO dApp, pasi Bob dhe Cooper plotësuan ia-depozita:
Funksioni ynë i depozitimit ka ndryshuar pak:
Tani vjen momenti më i rëndësishëm në aktivitetet e DAO - votoj për projektet që do të financohen.
Bob voton për projektin 500000 valëzues të Nelit:
broadcast(invokeScript({dappAddress: address(env.accounts[1]), call:{function:"vote",args:[{type:"integer", value: 500000}, {type:"string", value: "3MrXEKJr9nDLNyVZ1d12Mq4jjeUYwxNjMsH"}]}, payment: []}))
Në dyqanin e të dhënave shohim të gjitha shënimet e nevojshme për adresën e Nelit:
Cooper votoi gjithashtu për projektin Neli.
Le të hedhim një vështrim në kodin e funksionit merrni fondet. Neli duhet të mbledhë një minimum prej 2 votash që të mund të tërheqë fonde nga DAO.
Neli do të tërheqë gjysmën e shumës që i është besuar:
broadcast(invokeScript({dappAddress: address(env.accounts[1]), call:{function:"getFunds",args:[{type:"integer", value: 500000}]}, payment: []}))
Ajo ka sukses, domethënë DAO punon!
Ne shikuam procesin e krijimit të një DAO në gjuhë RIDE4DAPPS.
Në pjesët në vijim do t'i hedhim një vështrim më të afërt rifaktorimit të kodit dhe testimit të rasteve.
Versioni i plotë i kodit në
# 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
}
}
Burimi: www.habr.com