1. 程式人生 > >以太坊dapp智慧合約示例——通過對映使用者來玩彩票

以太坊dapp智慧合約示例——通過對映使用者來玩彩票

在前面的一些文章中,我們學習了以太坊智慧合約程式設計的基礎知識。現在我們來建立一個實戰以太坊dapp案例:彩票。

我們彩票案例的目的是多個玩家能夠通過傳送錢參與彩票。玩家傳送的錢越多,他贏得所有資金的機會就越大。當彩票的運營發行者決定關閉彩票後,就會選擇一個優勝者,並將全部資金轉給這名優勝者。

為了儲存每個玩家的彩金,我們將看到一個新的資料型別,這就是mappingmappingkey繫結到一個值。宣告必須同時指定key的型別和值。例如,這裡我們將儲存屬於某個地址的錢:

mapping(address => uint) usersBet;

usersBet[msg.sender] = 10
; // usersBet[msg.sender] == 10

不爽的是如果索引不是線性的,即使我們知道記錄的數量,也無法迭代mapping的值。因此,為了迭代我們的彩金,我們需要單獨地儲存玩家的數量和玩家在另一個對映中的地址列表。

所以我們將儲存3個變數包括彩票運營發行者的地址:

mapping(address => uint) usersBet;
mapping(uint => address) users;
uint nbUsers = 0;
uint totalBets = 0;

address owner;

我們然後構建一個Bet函式。正常賬戶一樣,智慧合約可以操控以太坊。我們Bet

函式需要有一個支付彩金的功能。當函式被呼叫的時候他就將投入的彩金值傳送給以太坊智慧合約,並將傳送以太幣的數量儲存在msg.value

所以當函式被呼叫時,我們先檢查傳送的以太幣值是否大於零即msg.value>0。然後我們將傳送值儲存在usersBet的對映中。如果這個玩家的彩金等於0,我們遞增我們的nbUsers並存儲玩家的地址,這樣我們可以在關閉這一期彩票時遍歷所有玩家。。

function Bet() public payable  {
    if (msg.value > 0) {
       if (usersBet[msg.sender] == 0) { // Is it a new player
users[nbUsers] = msg.sender; nbUsers += 1; } usersBet[msg.sender] += msg.value; totalBets += msg.value; } }

我們的彩票dapp的最後一部分是挑選優勝者。我們的函式EndLottery()只能由彩票的所有者訪問。為了簡化程式,我們將選擇一個隨機數在0與玩家數量之間。然後,我們將進行迭代篩選,並檢查誰贏了。當玩家被發現時,我們會簡單地將智慧合約作為確認優勝者的一個主要依據。他將得到合約中所有的錢。

function EndLottery() public {
    if (msg.sender == owner) {
        uint sum = 0; 
        uint winningNumber = uint(block.blockhash(block.number-1)) % totalBets;
        for (uint i=0; i < nbUsers; i++) {
           sum += usersBet[users[i]]; 
           if (sum >= winningNumber) {
               selfdestruct(users[i]);
               return;
           }
        }
    }
}

一個特別的說明,我們在這個示例中使用了一個非常簡單的方法來獲取或取值,現實中特別是在處理錢的時候,你需要用一個更好的方法來獲得真正的隨機數。

下面所有的智慧合約程式碼放在一起:

pragma solidity ^0.4.11;

contract Lottery {

    mapping(address => uint) usersBet;
    mapping(uint => address) users;
    uint nbUsers = 0;
    uint totalBets = 0;

    address owner;

    function Lottery() {
        owner = msg.sender;
    }

    function Bet() public payable  {
        if (msg.value > 0) {
            if (usersBet[msg.sender] == 0) {
                users[nbUsers] = msg.sender;
                nbUsers += 1;
            }
            usersBet[msg.sender] += msg.value;
            totalBets += msg.value;
        }
    }

    function EndLottery() public {
        if (msg.sender == owner) {
            uint sum = 0;
            uint winningNumber = uint(block.blockhash(block.number-1)) % totalBets + 1;
            for (uint i=0; i < nbUsers; i++) {
                sum += usersBet[users[i]];
                if (sum >= winningNumber) {
                    selfdestruct(users[i]);
                    return;
                }
            }
        }
    }

}

所以讓我們部署我們的合約並且來玩一把。我們將用我們的兩個賬戶來發送彩金用以太坊幣。作為一個功能你會看到我們可以呼叫函式payable進行支付。

傳送了以太幣後,你會發現智慧合約現在成立了。

如果你從彩票運營者賬戶呼叫EntLoTyTye()函式,彩票收益將轉移給優勝者,並且智慧合約也將結束。

在本文中,我們使用payable修飾符,使它可以傳送以太幣到我們的智慧合約。

  • 以太坊dapp,主要介紹智慧合約與dapp應用開發,適合入門。
  • 以太坊開發,主要是介紹使用node.js、mongodb、區塊鏈、ipfs實現去中心化電商DApp實戰,適合進階。

原文轉自這個以太坊部落格