Bonghjornu ognunu!
В
Testemu un pocu avà u disassemblatu
Stage 3. Testing u contu dApp
Chì prublemi ti saltanu immediatamente cun Alice? dApp U so contu?
Prima:
Boob è Cooper ponu accidentalmente mandà fondi à l'indirizzu dApp utilizendu regularmente trasferimentu transazzione è cusì ùn sarà capaci di accede à elli daretu.Siconda:
Ùn limitemu micca Alice in alcun modu da ritirare fondi senza l'appruvazioni di Boob è / o Cooper. Dapoi, fate attenzione à verificà, tutte e transazzione da Alice seranu eseguite.
Fixemu a 2ª pruibiscendu Alice trasferimentu transazzioni. Implementemu u script currettu:

Pruvamu di ritirà muniti da dApp Alice è a so firma. Avemu un errore:
Pruvemu di ritirà via ritirata:
broadcast(invokeScript({dappAddress: address(env.accounts[1]), call:{function:"withdraw",args:[{type:"integer", value: 1000000}]}, payment: []}))
U script funziona è avemu capitu u 2u puntu!
Stage 4. Crea un DAO cù votu
Sfurtunatamente, a lingua RIDE ùn furnisce ancu a capacità di travaglià cù cullezzione (dizziunarii, iteratori, riduttori, etc.). Tuttavia, per ogni operazione cù cullezzione flat chjave-valore pudemu disignà un sistema per travaglià cù strings, in cunseguenza cù i chjavi è a so decryption.
E stringhe sò assai faciuli di concatenate; i stringi ponu esse separati da indici.
Raccogliemu è analizà una stringa cum'è un esempiu di prova è verificate cumu questu affetta u risultatu di a transazzione.
Avemu stabilitu nantu à u fattu chì Alice ùn pudia micca firmà a transazzione di trasferimentu, postu chì sta capacità hè stata bluccata in @verifier per stu tipu di transazzione.
Pratichemu cù e corde è poi risolve questu.
Corde RIDE
A transazzione hè pussibule di novu, sapemu cumu travaglià cù strings.

In tuttu, avemu tuttu ciò chì hè necessariu per scrive una logica cumplessa DAO dApp.
Transazzione di dati
Transazzioni di dati:
"A dimensione massima per una chjave hè di 100 caratteri, è una chjave pò cuntene punti di codice Unicode arbitrarii cumpresi spazii è altri simboli non stampabili. I valori di stringa anu un limitu di 32,768 100 bytes è u numeru massimu di entrate pussibuli in a transazzione di dati hè 140. In generale, a dimensione massima di una transazzione di dati hè di circa XNUMX kb - per riferimentu, quasi esattamente a durata di l'opera di Shakespeare "Romeo and Juliet". '. "
Creemu un DAO cù e seguenti cundizioni:
Per chì una startup riceve un finanziamentu chjamendu ottene fondi () u sustegnu di almenu 2 participanti - investitori DAO - hè necessariu. Ritirassi serà pussibule esattamente quant'è u tutale indicatu vutatu I pruprietarii di DAO.
Facemu 3 tipi di chjavi è aghjunghje logica per travaglià cù saldi in 2 funzioni novi vote è getFunds:
xx...xx_ia = investitori, saldo dispunibule (vote, depositu, ritirata)
xx...xx_sv = startups, numeru di voti (vote, uttene i fondi)
xx...xx_sf = startups, numeru di voti (vote, uttene i fondi)
xx…xx = indirizzu publicu (35 caratteri)
Per piacè nutate chì in Vote avemu bisognu di aghjurnà parechji campi à una volta:
WriteSet([DataEntry(key1, value1), DataEntry(key2, value2)]),
WriteSet ci permette di fà parechji registri à una volta in unu invokeScript transazzioni.
Questu hè ciò chì pare in l'almacenamiento di u valore chjave di u DAO dApp, dopu chì Bob è Cooper si rimpianu. ia- depositi:
A nostra funzione di depositu hà cambiatu pocu:
Avà vene u mumentu più impurtante in l'attività di u DAO - vutà per i prughjetti da esse finanziati.
Bob vota per u prughjettu di 500000 wavelets di Neli:
broadcast(invokeScript({dappAddress: address(env.accounts[1]), call:{function:"vote",args:[{type:"integer", value: 500000}, {type:"string", value: "3MrXEKJr9nDLNyVZ1d12Mq4jjeUYwxNjMsH"}]}, payment: []}))
In u magazzinu di dati vedemu tutte e voci necessarie per l'indirizzu di Neli:
Cooper hà ancu vutatu per u prughjettu Neli.
Fighjemu un ochju à u codice di a funzione ottene i fondi. Neli deve cullà un minimu di 2 voti per pudè ritirà fondi da u DAO.
Neli hà da ritirarà a mità di a quantità chì li hè affidata :
broadcast(invokeScript({dappAddress: address(env.accounts[1]), call:{function:"getFunds",args:[{type:"integer", value: 500000}]}, payment: []}))
Ella riesce, vale à dì, DAO travaglia !
Avemu vistu u prucessu di creà un DAO in a lingua RIDE4DAPPS.
In i seguenti parti, daremu un ochju più vicinu à a refactoring di codice è a prova di casu.
Versione cumpleta di u codice in
# 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
}
}
Source: www.habr.com