学习在 RIDE 和 RIDE4DAPPS 上编写 Waves 智能合约。 第 2 部分(DAO - 去中心化自治组织)

学习在 RIDE 和 RIDE4DAPPS 上编写 Waves 智能合约。 第 2 部分(DAO - 去中心化自治组织)

您好!

В 第一 我们详细研究了如何创建和使用 dApp(去中心化应用程序) Waves RIDE IDE.

现在我们拆开来测试一下 例子.

第 3 阶段. 测试 dApp 帐户

学习在 RIDE 和 RIDE4DAPPS 上编写 Waves 智能合约。 第 2 部分(DAO - 去中心化自治组织)

与爱丽丝在一起时,您立即会遇到什么问题? DAPP 帐户?
第一:
Boob 和 Cooper 可能会意外地使用常规方式将资金发送到 dApp 地址 转让 交易,因此将无法访问它们。

第二:
未经 Boob 和/或 Cooper 批准,我们不会以任何方式限制 Alice 提取资金。因为,注意验证,所有来自Alice的交易都会被执行。

让我们通过禁止 Alice 来解决第二个问题 转让 交易。让我们部署更正后的脚本:
学习在 RIDE 和 RIDE4DAPPS 上编写 Waves 智能合约。 第 2 部分(DAO - 去中心化自治组织)

我们正在尝试从 dApp Alice 和她的签名中提取代币。我们得到一个错误:
学习在 RIDE 和 RIDE4DAPPS 上编写 Waves 智能合约。 第 2 部分(DAO - 去中心化自治组织)

让我们尝试通过withdraw来提现:

broadcast(invokeScript({dappAddress: address(env.accounts[1]), call:{function:"withdraw",args:[{type:"integer", value: 1000000}]}, payment: []}))

脚本成功了,我们找到了第二点!

第 4 阶段:创建一个带有投票功能的 DAO

不幸的是,RIDE 语言尚未提供使用集合(字典字典、迭代器、化简器等)的能力。但是,对于任何使用平面集合的操作 核心价值 我们可以设计一个处理字符串的系统,相应地使用密钥及其解密。

字符串非常容易连接;字符串可以通过索引分隔。
让我们收集并解析一个字符串作为测试示例,并检查这如何影响交易的结果。
我们确定了 Alice 无法签署 Transfer 交易的事实,因为这种能力在此类交易的 @verifier 中被阻止。

让我们用字符串练习一下,然后解决这个问题。

骑行弦

交易再次成为可能,我们知道如何使用字符串。
学习在 RIDE 和 RIDE4DAPPS 上编写 Waves 智能合约。 第 2 部分(DAO - 去中心化自治组织)


总的来说,我们拥有编写复杂逻辑所需的一切 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- 存款:
学习在 RIDE 和 RIDE4DAPPS 上编写 Waves 智能合约。 第 2 部分(DAO - 去中心化自治组织)

我们的存款功能略有变化:
学习在 RIDE 和 RIDE4DAPPS 上编写 Waves 智能合约。 第 2 部分(DAO - 去中心化自治组织)

现在到了 DAO 活动中最重要的时刻 - 投票 对于要融资的项目。

Bob 投票支持 Neli 的 500000 个小波项目:

broadcast(invokeScript({dappAddress: address(env.accounts[1]), call:{function:"vote",args:[{type:"integer", value: 500000}, {type:"string", value: "3MrXEKJr9nDLNyVZ1d12Mq4jjeUYwxNjMsH"}]}, payment: []}))

学习在 RIDE 和 RIDE4DAPPS 上编写 Waves 智能合约。 第 2 部分(DAO - 去中心化自治组织)

在数据存储中,我们看到 Neli 地址的所有必要条目:
学习在 RIDE 和 RIDE4DAPPS 上编写 Waves 智能合约。 第 2 部分(DAO - 去中心化自治组织)
Cooper 也投票支持了 Neli 项目。
学习在 RIDE 和 RIDE4DAPPS 上编写 Waves 智能合约。 第 2 部分(DAO - 去中心化自治组织)

我们看一下函数代码 获取资金。 Neli 必须至少收集 2 票才能从 DAO 提取资金。
学习在 RIDE 和 RIDE4DAPPS 上编写 Waves 智能合约。 第 2 部分(DAO - 去中心化自治组织)

Neli准备提取一半委托给她的金额:

broadcast(invokeScript({dappAddress: address(env.accounts[1]), call:{function:"getFunds",args:[{type:"integer", value: 500000}]}, payment: []}))

学习在 RIDE 和 RIDE4DAPPS 上编写 Waves 智能合约。 第 2 部分(DAO - 去中心化自治组织)

她成功了,那就是DAO起作用了!

我们研究了用该语言创建 DAO 的过程 RIDE4DAPPS.
在以下部分中,我们将仔细研究代码重构和案例测试。

完整版代码在 波浪骑行IDE:

# 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
    }
}

的第一部分
GitHub 上的代码
Waves RIDE IDE
资助计划的公告

来源: habr.com

添加评论