您好!
В
现在我们拆开来测试一下
第 3 阶段. 测试 dApp 帐户
与爱丽丝在一起时,您立即会遇到什么问题? DAPP 帐户?
第一:
Boob 和 Cooper 可能会意外地使用常规方式将资金发送到 dApp 地址 转让 交易,因此将无法访问它们。第二:
未经 Boob 和/或 Cooper 批准,我们不会以任何方式限制 Alice 提取资金。因为,注意验证,所有来自Alice的交易都会被执行。
让我们通过禁止 Alice 来解决第二个问题 转让 交易。让我们部署更正后的脚本:

我们正在尝试从 dApp Alice 和她的签名中提取代币。我们得到一个错误:
让我们尝试通过withdraw来提现:
broadcast(invokeScript({dappAddress: address(env.accounts[1]), call:{function:"withdraw",args:[{type:"integer", value: 1000000}]}, payment: []}))
脚本成功了,我们找到了第二点!
第 4 阶段:创建一个带有投票功能的 DAO
不幸的是,RIDE 语言尚未提供使用集合(字典字典、迭代器、化简器等)的能力。但是,对于任何使用平面集合的操作 核心价值 我们可以设计一个处理字符串的系统,相应地使用密钥及其解密。
字符串非常容易连接;字符串可以通过索引分隔。
让我们收集并解析一个字符串作为测试示例,并检查这如何影响交易的结果。
我们确定了 Alice 无法签署 Transfer 交易的事实,因为这种能力在此类交易的 @verifier 中被阻止。
让我们用字符串练习一下,然后解决这个问题。
骑行弦
交易再次成为可能,我们知道如何使用字符串。

总的来说,我们拥有编写复杂逻辑所需的一切 DAO dApp.
数据交易
数据交易:
“密钥的最大大小为 100 个字符,并且密钥可以包含任意 Unicode 代码点,包括空格和其他不可打印的符号。字符串值的限制为 32,768 字节,数据事务中可能的最大条目数为 100。总体而言,数据事务的最大大小约为 140kb — 作为参考,几乎恰好是莎士比亚戏剧《罗密欧与朱丽叶》的长度'。”
我们创建一个 DAO 并满足以下条件:
为了让初创公司通过致电获得资金 获取资金() 需要至少 2 位参与者(DAO 投资者)的支持。 撤 可能与上所示的总数完全相同 表决 DAO 所有者。
让我们创建 3 种类型的键,并在 2 个新函数 vote 和 getFunds 中添加处理余额的逻辑:
xx…xx_ia = 投资者、可用余额 (投票、充值、提现)
xx…xx_sv = 初创公司, 票数 (投票,获取资金)
xx…xx_sf = 初创公司, 票数 (投票,获取资金)
xx…xx = 公共地址(35 个字符)
请注意,在投票中我们需要一次更新多个字段:
WriteSet([DataEntry(key1, value1), DataEntry(key2, value2)]),
WriteSet 允许我们在一个记录中同时创建多条记录 调用脚本 交易。
这就是 Bob 和 Cooper 补充后 DAO dApp 的键值存储中的样子 ia- 存款:
我们的存款功能略有变化:
现在到了 DAO 活动中最重要的时刻 - 投票 对于要融资的项目。
Bob 投票支持 Neli 的 500000 个小波项目:
broadcast(invokeScript({dappAddress: address(env.accounts[1]), call:{function:"vote",args:[{type:"integer", value: 500000}, {type:"string", value: "3MrXEKJr9nDLNyVZ1d12Mq4jjeUYwxNjMsH"}]}, payment: []}))
在数据存储中,我们看到 Neli 地址的所有必要条目:
Cooper 也投票支持了 Neli 项目。
我们看一下函数代码 获取资金。 Neli 必须至少收集 2 票才能从 DAO 提取资金。
Neli准备提取一半委托给她的金额:
broadcast(invokeScript({dappAddress: address(env.accounts[1]), call:{function:"getFunds",args:[{type:"integer", value: 500000}]}, payment: []}))
她成功了,那就是DAO起作用了!
我们研究了用该语言创建 DAO 的过程 RIDE4DAPPS.
在以下部分中,我们将仔细研究代码重构和案例测试。
完整版代码在
# 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
}
}
来源: habr.com