以太坊dapp智慧合約示例——通過對映使用者來玩彩票
在前面的一些文章中,我們學習了以太坊智慧合約程式設計的基礎知識。現在我們來建立一個實戰以太坊dapp案例:彩票。
我們彩票案例的目的是多個玩家能夠通過傳送錢參與彩票。玩家傳送的錢越多,他贏得所有資金的機會就越大。當彩票的運營發行者決定關閉彩票後,就會選擇一個優勝者,並將全部資金轉給這名優勝者。
為了儲存每個玩家的彩金,我們將看到一個新的資料型別,這就是mapping
。mapping
將key
繫結到一個值。宣告必須同時指定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
修飾符,使它可以傳送以太幣到我們的智慧合約。
原文轉自這個以太坊部落格