Hello!
Π
Sekarang mari kita uji sedikit yang dibongkar
Tahap 3. Menguji akun dApp
Masalah apa yang segera mengalir ke suara-suara dengan Alice dApp Rekening?
Pertama:
Boob dan Cooper mungkin secara tidak sengaja mengirim dana ke alamat dApp menggunakan yang biasa transfer transaksi dan dengan demikian tidak akan dapat mengaksesnya kembali.Kedua:
Kami sama sekali tidak membatasi Alice untuk menarik dana tanpa persetujuan dari Boob dan/atau Cooper. Karena, perhatikan verifikasi, semua transaksi dari Alice akan dieksekusi.
Mari perbaiki 2 dengan melarang Alice transfer transaksi. Terapkan skrip yang diperbaiki:
οΏΌ
Kami mencoba menarik koin dengan dApp Alice dan tanda tangannya. Kami mendapatkan kesalahan:
Mencoba menarik melalui penarikan:
broadcast(invokeScript({dappAddress: address(env.accounts[1]), call:{function:"withdraw",args:[{type:"integer", value: 1000000}]}, payment: []}))
Skripnya berfungsi dan kami menemukan poin ke-2!
Tahap 4. Buat DAO dengan pemungutan suara
Sayangnya, bahasa RIDE belum menyediakan kemampuan untuk bekerja dengan koleksi (kamus, kamus, iterator, reduksi, dll.). Namun, untuk setiap operasi pada koleksi datar nilai kunci kita dapat merancang sistem untuk bekerja dengan string, masing-masing dengan kunci dan dekripsinya.
String sangat mudah digabungkan, string dapat dipisahkan dengan indeks.
Mari kumpulkan dan parsing string sebagai kasus uji dan periksa bagaimana hal ini akan memengaruhi hasil transaksi.
Kami menetapkan fakta bahwa Alice tidak dapat menandatangani transaksi Transfer, karena kemungkinan ini diblokir di @verifier untuk jenis transaksi ini.
Mari berlatih dengan string lalu selesaikan ini.
RIDE String
Transaksi dimungkinkan lagi, kami tahu cara bekerja dengan string.
οΏΌ
Secara total, kami memiliki semua yang Anda butuhkan untuk menulis logika kompleks DAO dApp.
Transaksi Data
Transaksi Data:
βUkuran maksimum untuk sebuah kunci adalah 100 karakter, dan sebuah kunci dapat berisi poin kode Unicode arbitrer termasuk spasi dan simbol lain yang tidak dapat dicetak. Nilai string memiliki batas 32,768 byte dan jumlah maksimum entri yang mungkin dalam transaksi data adalah 100. Secara keseluruhan, ukuran maksimum transaksi data adalah sekitar 140kb β untuk referensi, hampir sama dengan panjang drama Shakespeare 'Romeo and Juliet '. β
Kami membuat DAO dengan ketentuan sebagai berikut:
Agar startup mendapatkan pendanaan dengan menelepon dapatkan Dana() dukungan minimal 2 peserta - investor DAO diperlukan. menarik itu akan mungkin persis sebanyak jumlah yang ditunjukkan pemungutan suara pemilik DAO.
Mari buat 3 jenis kunci dan tambahkan logika untuk bekerja dengan saldo dalam 2 fungsi baru, pilih dan dapatkan Dana:
xxβ¦xx_ia = investor, saldo tersedia (suara, deposit, penarikan)
xxβ¦xx_sv = startup, jumlah suara (pilih, dapatkan Dana)
xxβ¦xx_sf = startup, jumlah suara (pilih, dapatkan Dana)
xxβ¦xx = alamat publik (35 karakter)
Perhatikan di Vote kami perlu memperbarui beberapa bidang sekaligus:
WriteSet([DataEntry(key1, value1), DataEntry(key2, value2)]),
WriteSet memungkinkan kita membuat beberapa record sekaligus dalam satu invokeScript transaksi.
Beginilah tampilannya di penyimpanan nilai kunci DAO dApp setelah Bob dan Cooper diisi ulang ia- deposito:
Fungsi setoran kami sedikit berubah:
Sekarang tibalah momen terpenting dalam aktivitas DAO - Pilih untuk proyek-proyek untuk pendanaan.
Bob memilih proyek Neli pada 500000 wavelet:
broadcast(invokeScript({dappAddress: address(env.accounts[1]), call:{function:"vote",args:[{type:"integer", value: 500000}, {type:"string", value: "3MrXEKJr9nDLNyVZ1d12Mq4jjeUYwxNjMsH"}]}, payment: []}))
Di penyimpanan data, kami melihat semua entri yang diperlukan untuk alamat Neli:
Cooper juga memilih proyek Neli.
Mari kita lihat kode fungsinya dapatkan Dana. Neli harus mengumpulkan minimal 2 suara untuk dapat mencairkan dana dari DAO.
Neli akan menarik setengah dari jumlah yang dipercayakan kepadanya:
broadcast(invokeScript({dappAddress: address(env.accounts[1]), call:{function:"getFunds",args:[{type:"integer", value: 500000}]}, payment: []}))
Dia berhasil, yaitu, DAO berfungsi!
Kami meninjau proses pembuatan DAO dalam bahasa tersebut RIDE4DAPPS.
Pada bagian berikut, kita akan melihat lebih dekat pemfaktoran ulang kode dan pengujian kasus.
Kode lengkap di
# 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
}
}
Sumber: www.habr.com