以太坊 solidity 隨機抽獎合約——搏一搏,單車變摩托

許文強發表於2018-09-02

   最近準備做一個以太坊的抽獎遊戲,今天先把合約完成。

   智慧合約只實現關鍵部分的功能,包括隨機選取中獎者,儲存每個人的中獎情況,以及開獎的時機;

現在我們一個一個模組來說一下;

第一個選擇中獎者,這個函式的基礎是生成隨機數;

function winnerNumber() private returns(uint) {
        uint winner = uint(keccak256(abi.encodePacked(now, msg.sender, nonce))) % 3;
        nonce++;
        return winner;
    }

我們使用時間、抽獎著地址、nonce值,通過encodePacked進行編碼,然後進行hash處理(keccak256);取得一個隨機數,然後對3取餘,就可以隨機選取一個獲勝者;其實目前以太坊智慧合約中很難生成無法預測的隨機數,可以使用Oracalize服務,不過是收費的。不過個人覺得資金比較小的時候,其實還是可以使用時間,blockhash等鏈上資訊生產隨機數,如果資金比較大了之後,需要注意。

第二個參加抽獎,這個函式逼近簡單,就是記錄了參加抽獎人的地址資訊;

    function draw() public payable {
        require(msg.value == 0.01 ether);
        require(participantsCount < 3);
        require(drawSituation(msg.sender) == false);
        cormorants[Count] = msg.sender;
        Count++;
        if (Count == 3) {
            produceWinner();
        }
    }

    function drawSituation(address _cormorant) private view returns(bool) {
        bool contains = false;
        for(uint i = 0; i < 3; i++) {
            if (cormorants[i] == _cormorant) {
                contains = true;
            }
        }
        return contains;
    }

這個沒有太複雜需要解釋的,就是當有三個人蔘加抽獎之後,就開獎了;

第三個選擇中獎者,這個函式其實是第一個函式的一個封裝;

    function produceWinner() private returns(address) {
        require(Count == 3);
        address winner = cormorants[winnerNumber()];
        winner.transfer(address(this).balance);
        delete cormorants;
        Count = 0;
        return winner;
    }

選擇了中獎者之後,把獎池裡的所有獎金都傳送飛中獎者;

到這已經把抽獎的智慧合約寫完了,這裡只是簡單寫了一個模版,需要複雜功能的朋友,例如,人數,中獎時機,獎金分配方式等,可以自行進行修改除錯。

github 地址:https://github.com/XuHugo/solidityproject/tree/master/lottery

相關文章