Hola a todos!
Π
Proba dezagun orain desmuntatutakoa apur bat
3. etapa. dApp kontua probatzen
Zer arazo berehala Alicerekin ahotsetara dApp Kontua?
Lehenik eta behin:
Boob eta Cooper-ek ustekabean dirua bidal ditzakete dApp helbide batera normal bat erabiliz transferitzeko transakzioak eta, beraz, ezin izango dira atzera sartu.Bigarrenik:
Ez dugu inola ere mugatzen Alice funtsak ateratzea Boob eta/edo Cooperren baimenik gabe. Geroztik, arreta jarri egiaztatzeko, Aliceren transakzio guztiak exekutatu egingo dira.
Konpon dezagun 2 Alice debekatuz transferitzeko transakzioak. Inplementatu zuzendutako scripta:
οΏΌ
DApp Alice eta bere sinadurarekin txanponak erretiratzen saiatzen ari gara. Errore bat jasoko dugu:
Erretiratzearen bidez erretiratzen saiatzen:
broadcast(invokeScript({dappAddress: address(env.accounts[1]), call:{function:"withdraw",args:[{type:"integer", value: 1000000}]}, payment: []}))
Gidoiak funtzionatzen du eta 2. puntua asmatu dugu!
4. etapa. Sortu DAO bat bozketarekin
Zoritxarrez, RIDE hizkuntzak ez du oraindik bildumekin lan egiteko gaitasunik ematen (hiztegiak, hiztegiak, iteratzaileak, murriztaileak, etab.). Hala ere, bilduma lauen gaineko edozein eragiketetarako gako-balioa kateekin lan egiteko sistema bat diseina dezakegu, hurrenez hurren gakoekin eta haien deszifraketarekin.
Kateak kateatzen oso errazak dira, kateak indizeen bidez bereiz daitezke.
Bildu eta analiza ditzagun katea test kasu gisa eta egiaztatu horrek transakzioaren emaitzan nola eragingo duen.
Alicek Transferentzia transakzioa sinatu ezin zuela erabaki genuen, aukera hori @verifier-en blokeatuta zegoen transakzio mota honetarako.
Praktikatu dezagun kateekin eta ebatzi dezagun.
RIDE kateak
Transakzioa posible da berriro, kateekin lan egiten badakigu.
οΏΌ
Guztira, logika konplexua idazteko behar duzun guztia dugu DAO dApp.
Datu-transakzioak
Datu transakzioak:
"Gako baten gehienezko tamaina 100 karakterekoa da, eta gako batek Unicode kode puntu arbitrarioak izan ditzake zuriuneak eta inprimagarriak ez diren beste sinbolo batzuk barne. Kate-balioek 32,768 byte-ko muga dute eta datu-transakzioan sartze posibleen gehienezko kopurua 100 da. Orokorrean, datu-transakzio baten gehienezko tamaina 140 kb ingurukoa da - erreferentzia gisa, Shakespeareren "Romeo eta Julieta" antzezlanaren ia zehatz-mehatz. '."
DAO bat sortzen dugu baldintza hauekin:
Startup batek deituz finantzaketa lor dezan lortu funtsak() gutxienez 2 parte-hartzaileren laguntza - DAO inbertitzaileak behar da. erretiratuko gainean adierazitako batura bezainbeste posible izango da bozketa DAO jabeak.
Egin ditzagun 3 gako mota eta gehitu logika saldoekin lan egiteko 2 funtzio berritan bozkatu eta lortuFunds:
xx...xx_ia = inbertitzaileak, saldo erabilgarria (botoa, gordailua, kentzea)
xx...xx_sv = startup-ak, boto kopurua (bozkatu, lortu funtsak)
xx...xx_sf = startup-ak, boto kopurua (bozkatu, lortu funtsak)
xxβ¦xx = helbide publikoa (35 karaktere)
Oharra Bozketan hainbat eremu aldi berean eguneratu behar ditugula:
WriteSet([DataEntry(key1, value1), DataEntry(key2, value2)]),
WriteSet-ek hainbat erregistro aldi berean egiteko aukera ematen digu bakar baten barruan invokeScript transakzioak.
Honela ikusten da DAO dApp-ren gako-balioen biltegian, Bob eta Cooper-ek bete ondoren ia- Gordailuak:
Gure gordailu-funtzioa zertxobait aldatu da:
Orain dator DAOren jardueren unerik garrantzitsuena - bozkatu finantzaketa-proiektuetarako.
Bob-ek Neli proiektuaren alde bozkatu du 500000 uhinetan:
broadcast(invokeScript({dappAddress: address(env.accounts[1]), call:{function:"vote",args:[{type:"integer", value: 500000}, {type:"string", value: "3MrXEKJr9nDLNyVZ1d12Mq4jjeUYwxNjMsH"}]}, payment: []}))
Datu biltegian, Neli helbiderako beharrezko sarrera guztiak ikusiko ditugu:
Cooperek ere Neli proiektuaren alde bozkatu zuen.
Ikus dezagun funtzioaren kodea lortu funtsak. Nelik gutxienez 2 boto bildu behar ditu DAOtik funtsak atera ahal izateko.
Nelik agindutako zenbatekoaren erdia aterako du:
broadcast(invokeScript({dappAddress: address(env.accounts[1]), call:{function:"getFunds",args:[{type:"integer", value: 500000}]}, payment: []}))
Lortzen du, hau da, DAOk funtzionatzen du!
Hizkuntzan DAO bat sortzeko prozesua aztertu dugu RIDE4DAPPS.
Ondorengo zatietan, kodearen birfaktorizazioa eta kasuen probak aztertuko ditugu.
Kode osoa sartu
# 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
}
}
Iturria: www.habr.com