學習在 RIDE 和 RIDE4DAPPS 上編寫 Waves 智能合約。 第 2 部分(DAO - 去中心化自治組織)

學習在 RIDE 和 RIDE4DAPPS 上編寫 Waves 智能合約。 第 2 部分(DAO - 去中心化自治組織)

大家好!

В 第一個 在本部分中,我們詳細研究瞭如何在 Waves Ride IDE.

現在讓我們稍微測試一下拆開的 例子.

步驟3.測試dApp帳戶

學習在 RIDE 和 RIDE4DAPPS 上編寫 Waves 智能合約。 第 2 部分(DAO - 去中心化自治組織)

哪些問題會立即引起 Alice 的注意 DAPP 帳戶?
首先:
Boob 和 Cooper 可能會意外地使用常規 轉讓 交易,因此將無法重新訪問它們。

其次:
未經 Boob 或(和)Cooper 同意,我們不會以任何方式限制 Alice 提取資金。請注意驗證,所有來自 Alice 的交易都將被執行。

讓我們透過禁止 Alice 來解決第二個問題 轉讓 交易。部署更正後的腳本:
學習在 RIDE 和 RIDE4DAPPS 上編寫 Waves 智能合約。 第 2 部分(DAO - 去中心化自治組織)

我們嘗試從 dApp Alice 及其簽章中提取幣。結果出現錯誤:
學習在 RIDE 和 RIDE4DAPPS 上編寫 Waves 智能合約。 第 2 部分(DAO - 去中心化自治組織)

讓我們嘗試透過提款來提款:

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

腳本運作正常,我們已經解決了第 2 點!

步驟 4:創建具有投票功能的 DAO

遺憾的是,RIDE 語言目前不支援處理集合(字典的字典、迭代器、reducer 等)。然而,對於任何平面集合的操作 核心價值 我們可以設計一個處理字串的系統,並相應地設計金鑰及其解密。

字串很容易連接,字串可以透過索引拆分。
讓我們組裝和反彙編一個字串作為測試範例,並檢查這如何影響交易的結果。
最終,Alice 無法簽署轉帳交易,因為此功能在 @verifier 中被封鎖用於此類交易。

讓我們用琴弦練習一下,然後解決這個問題。

RIDE琴弦

交易再次成為可能,我們知道如何處理字串。
學習在 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 以 500000 萬個小波為 Neli 的項目投票:

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.
在接下來的部分我們將更詳細地討論程式碼重構和案例測試。

完整版程式碼 Waves RIDE 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
資助計畫公告

來源: www.habr.com

為具有 DDoS 保護、VPS VDS 服務器的站點購買可靠的主機 🔥 購買具備 DDoS 防護的可靠網站寄存服務,包括 VPS 和 VDS 伺服器 | ProHoster