摘要:合約編寫可以看出合約需要實(shí)現(xiàn)用戶投注生成隨機(jī)數(shù)發(fā)放獎(jiǎng)勵(lì)獎(jiǎng)池余額查詢的功能,接下來編寫我們的合約代碼??偨Y(jié)當(dāng)前隨機(jī)數(shù)的實(shí)現(xiàn)通過鏈上信息生成,這種生成隨機(jī)數(shù)的方式容易受到不誠實(shí)的節(jié)點(diǎn)攻擊。
導(dǎo)讀:
本文旨在引導(dǎo)對(duì) DApp 開發(fā)感興趣的開發(fā)者,構(gòu)建一個(gè)基于以太坊去中心化應(yīng)用,通過開發(fā)一款功能完備的競猜游戲,邁出 DApp 開發(fā)的第一步,通過實(shí)例講解 Solidity 語言的常用語法,以及前端如何與智能合約進(jìn)行交互。
如果正在閱讀的你,從未接觸過 DApp 開發(fā)也不要緊,可以先閱讀【區(qū)塊鏈上編程:DApp開發(fā)簡介】進(jìn)行前置知識(shí)補(bǔ)充。
隨著加密貓、FOMO3D 等游戲的火爆,去中心化應(yīng)用在游戲領(lǐng)域遍地開花,下面就帶著大家一起開發(fā)一款簡單有趣的 DApp 游戲,幫助大家熟悉 DApp 開發(fā)。
本 DApp 實(shí)現(xiàn)的合約功能:用戶從 0-6 的數(shù)字中,任意組合三位數(shù)進(jìn)行投注,合約計(jì)算出 3 位隨機(jī)數(shù),根據(jù)隨機(jī)數(shù)的組合規(guī)則分別給予用戶不同倍數(shù)的獎(jiǎng)勵(lì),如隨機(jī)數(shù)為 AAA ,A 等于 6 則獎(jiǎng)勵(lì)至少 20 倍投注金額,即獎(jiǎng)池所有余額;A 不等于 6 則獎(jiǎng)勵(lì) 5 倍投注金額;隨機(jī)數(shù)為 AAB,則獎(jiǎng)勵(lì) 2 倍投注金額;隨機(jī)數(shù)為 ABC 則不獎(jiǎng)勵(lì),同時(shí)用戶可查看獎(jiǎng)池余額和個(gè)人投注記錄。
合約編寫可以看出合約需要實(shí)現(xiàn)用戶投注、生成隨機(jī)數(shù)、發(fā)放獎(jiǎng)勵(lì)、獎(jiǎng)池余額查詢的功能,接下來編寫我們的合約代碼。
新建Lottery.sol合約文件,聲明合約版本,^表示合約編譯版本為 0.4.0 至 0.5.0(不含 0.5.0)。
pragma solidity ^0.4.0;
定義合約基本內(nèi)容,同時(shí)聲明最低投注金額。
contract Lottery { uint public betMoney = 10 finney; }
生成隨機(jī)數(shù),通過區(qū)塊難度block.difficulty和內(nèi)置函數(shù)keccak256生成隨機(jī)數(shù),在EVM中常用的數(shù)據(jù)存儲(chǔ)位置:memory、storage,函數(shù)的參數(shù)、返回值默認(rèn)存儲(chǔ)在memory中,狀態(tài)變量默認(rèn)存儲(chǔ)在storage中,我們可以通過聲明memory、storage改變默認(rèn)存儲(chǔ)位置,兩者的存儲(chǔ)都需要消耗gas,但storage的開銷遠(yuǎn)大于memory。
contract Lottery { ... function generateRandomNumber() private view returns(uint[]) { uint[] memory dices = new uint[](3); for (uint i = 0; i < 3; i++) { dices[i] = uint(keccak256(abi.encodePacked(block.difficulty, now, i))) % 6 + 1; } return dices; } ... }
獲取合約余額,address類型比較重要的成員屬性主要有balance、transfer,分別為獲取地址余額、轉(zhuǎn)移eth至該地址,默認(rèn)eth單位是wei。
contract Lottery { ... function getBankBalance() public view returns(uint) { return address(this).balance; } ... }
用戶投注,投注方法需要使用payable關(guān)鍵字描述,用來表示可以接收eth;通過msg.sender和msg.value獲得交易發(fā)送者地址和當(dāng)前交易附帶的eth。通常使用require來校驗(yàn)外部輸入?yún)?shù),當(dāng)判定條件為false時(shí),則會(huì)將剩余的gas退回,同時(shí)回滾交易;assert則用來處理合約內(nèi)部的邏輯錯(cuò)誤,當(dāng)錯(cuò)誤發(fā)生時(shí)會(huì)消耗掉所有gas,同時(shí)回滾交易。
contract Lottery { ... function bet() public payable { uint amount = msg.value; require(amount >= betMoney, "bet money not less than 10 finney"); require(address(this).balance >= amount * 20, "contract money not enough to pay reward"); uint[] memory dices = generateRandomNumber(); require(dices.length == 3, "dices illegal"); address addr = msg.sender; bool isReward = false; uint reward = 0; if ((dices[0] == dices[1]) && (dices[1] == dices[2]) && (dices[0] == 6)) { isReward = true; reward = address(this).balance; } else if ((dices[0] == dices[1]) && (dices[1] == dices[2]) && (dices[0] != 6)) { isReward = true; reward = amount * 5; } else if ((dices[0] == dices[1]) || (dices[0] == dices[2]) || (dices[1] == dices[2])) { isReward = true; reward = amount * 2; } if (isReward) { addr.transfer(reward); } } ...
定義事件,通過合約內(nèi)部觸發(fā)事件,web3 監(jiān)聽到事件回調(diào)進(jìn)行相應(yīng)邏輯處理,從而進(jìn)行頁面 UI 更新;同時(shí)前端也可以通過對(duì)應(yīng)事件名稱獲取日志信息。
contract Lottery { ... event BetList( address addr, uint amount, bool isReward, uint reward, uint[] dices ); function bet() public payable { ... emit BetList(addr, amount, isReward, reward, dices); } ...與合約進(jìn)行交互
至此,我們已經(jīng)寫完了合約代碼,前端頁面實(shí)現(xiàn)就不在此贅述,主要介紹如何使用 web3 與合約交互,這里使用到的 web3 版本是 1.0,web3 1.0 和 0.2x.x 的 API 調(diào)用方式差別較大,1.0 的 API 支持異步調(diào)用。
安裝 Metamask 瀏覽器插件后,會(huì)在瀏覽器頁面內(nèi)注入一個(gè) web3 實(shí)例。檢測頁面中是否存在 web3 實(shí)例,如果不存在則連接自己的實(shí)例。
import Web3 from "web3"; if (typeof web3 !== "undefined") { web3 = new Web3(web3.currentProvider); } else { web3 = new Web3(new Web3.providers.HttpProvider(NODE_NRL)); }
傳入合約 ABI,合約地址,實(shí)例化合約對(duì)象。
this.contract = new web3.eth.Contract( CONTRACT_ABI, CONTRACT_ADDR, );
調(diào)用合約中的投注方法,通過try catch可以捕獲到 Metamask 彈窗取消交易操作。
userBet = async () => { try { await this.contract.methods .bet( ... ) .send({ from: ACCOUNT, value: MONEY, }); } catch (error) { ... } }
查詢記錄的日志,可以通過指定事件名稱、區(qū)塊高度及過濾條件來進(jìn)行日志查詢,值得注意的是,在合約內(nèi)不能查詢到日志信息。
queryEvent = async () => { const event = await this.contract.getPastEvents( EVENT_NAME, { filter: {}, fromBlock: 0, toBlock: "latest", } ) }功能拓展
比如修改用戶投注金額及充值這類敏感操作,就需要管理員的權(quán)限來進(jìn)行操作。同樣地,我們也可以拓展贊助商的功能,通過充值獎(jiǎng)池的累計(jì)金額排名來展示贊助商的廣告,這里就不做展開了。
定義修飾器,在構(gòu)造函數(shù)里設(shè)置管理員地址,將創(chuàng)建合約的賬戶設(shè)置為管理員。
contract Lottery { ... address public owner; modifier onlyOwner() { require(owner == msg.sender); _; } constructor() public { owner = msg.sender; } ... }
實(shí)現(xiàn)修改投注金額的功能,僅管理員賬戶可觸發(fā)。
contract Lottery { ... function setBetMoney(uint _betMoney) public onlyOwner { betMoney = _betMoney; } function deposit() public payable onlyOwner {} ... }總結(jié)
當(dāng)前隨機(jī)數(shù)的實(shí)現(xiàn)通過鏈上信息生成,這種生成隨機(jī)數(shù)的方式容易受到不誠實(shí)的節(jié)點(diǎn)攻擊。下一篇文章將通過多個(gè)實(shí)例介紹相應(yīng)的第三方工具庫的使用(Oricalize、SafeMath、OpenZepplin),生成安全的隨機(jī)數(shù)。
參考資料Solidity
Web3js
Cryptozombies
Coursetro
前置文章:
在區(qū)塊鏈上編程:DApp 開發(fā)簡介
文 / ielapp
一個(gè)簡單的程序員編 / 熒聲
本文已由作者授權(quán)發(fā)布,版權(quán)屬于創(chuàng)宇前端。歡迎注明出處轉(zhuǎn)載本文。本文鏈接:https://knownsec-fed.com/2018...
想要訂閱更多來自知道創(chuàng)宇開發(fā)一線的分享,請(qǐng)搜索關(guān)注我們的微信公眾號(hào):創(chuàng)宇前端(KnownsecFED)。歡迎留言討論,我們會(huì)盡可能回復(fù)。
歡迎點(diǎn)贊、收藏、留言評(píng)論、轉(zhuǎn)發(fā)分享和打賞支持我們。打賞將被完全轉(zhuǎn)交給文章作者。
感謝您的閱讀。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/24326.html
摘要:目前通常指代基于以太坊或者上的智能合約開發(fā)的相關(guān)應(yīng)用。引入以太坊通過的交互流程大致如下總結(jié)隨著區(qū)塊鏈近些年的大紅大紫,被推上了風(fēng)口浪尖,本文從技術(shù)的角度大致介紹了一下所涉及的技術(shù)要點(diǎn)。 當(dāng)你開始探索區(qū)塊鏈開發(fā),需要了解到這些。 showImg(https://segmentfault.com/img/remote/1460000016608233?w=1370&h=389); 一、DA...
摘要:以太坊將成為新互聯(lián)網(wǎng)的支柱,我為什么這么說正在以太坊上構(gòu)建我們的第層,而不是其他區(qū)塊鏈平臺(tái)這就是原因。以太坊不會(huì)犧牲去中心化的原則而下沉權(quán)力在區(qū)塊鏈方面,有一項(xiàng)稱為可擴(kuò)展性三難的基本法則。 以太坊將成為新互聯(lián)網(wǎng)的支柱,我為什么這么說?Loom Network正在以太坊上構(gòu)建我們的第2層,而不是其他區(qū)塊鏈平臺(tái)——這就是原因。 每個(gè)月都有其他的公司發(fā)布白皮書,聲稱已經(jīng)解決了以太坊所面臨的可...
摘要:將基于和開發(fā)的放在區(qū)塊鏈系統(tǒng)上,結(jié)合智能合約,就成了。應(yīng)用的數(shù)據(jù)加密后存儲(chǔ)在公開的區(qū)塊鏈上,所有對(duì)基礎(chǔ)區(qū)塊鏈技術(shù)的安全性穩(wěn)定性及持續(xù)性要求較高。以太貓本身具有虛擬貨幣的功能,每只貓都是獨(dú)特的交易于區(qū)塊鏈的不可變更物體。啟迪云-高級(jí)開發(fā)工程師 嚴(yán)剛前言2018年以來,區(qū)塊鏈(blockchain)無疑是最火的科技之一,新聞媒體大量報(bào)道,宣稱它將創(chuàng)造未來。我們?cè)撛鯓訁⑴c?買幾個(gè)幣算不算呢?其實(shí)也...
摘要:下一代去中心化預(yù)言機(jī)服務(wù)網(wǎng)絡(luò)臺(tái)北圓滿落幕年月日,由,攜手共同聯(lián)合舉辦的臺(tái)北線下在臺(tái)北的聯(lián)合創(chuàng)業(yè)辦公社圓滿落幕。網(wǎng)絡(luò)擔(dān)任臺(tái)北站活動(dòng)嘉賓暨講師活動(dòng)開頭,由網(wǎng)絡(luò)介紹網(wǎng)絡(luò)本身架構(gòu)以及預(yù)言機(jī)在現(xiàn)實(shí)生活中的應(yīng)用場景,范例。 showImg(https://segmentfault.com/img/bVbrNsK?w=1200&h=800);下一代去中心化預(yù)言機(jī)服務(wù)網(wǎng)絡(luò)DOS Network臺(tái)北Me...
摘要:我們目前正處于一個(gè)新興的區(qū)塊鏈開發(fā)行業(yè)中。,一種在以太坊開發(fā)人員中流行的新的簡單編程語言,因?yàn)樗怯糜陂_發(fā)以太坊智能合約的語言。它是全球至少萬開發(fā)人員使用的世界上最流行的編程語言之一。以太坊,主要是針對(duì)工程師使用進(jìn)行區(qū)塊鏈以太坊開發(fā)的詳解。 我們目前正處于一個(gè)新興的區(qū)塊鏈開發(fā)行業(yè)中。區(qū)塊鏈技術(shù)處于初期階段,然而這種顛覆性技術(shù)已經(jīng)成功地風(fēng)靡全球,并且最近經(jīng)歷了一場與眾不同的繁榮。由于許多...
閱讀 2316·2021-10-13 09:39
閱讀 3429·2021-09-30 09:52
閱讀 812·2021-09-26 09:55
閱讀 2788·2019-08-30 13:19
閱讀 1904·2019-08-26 10:42
閱讀 3199·2019-08-26 10:17
閱讀 554·2019-08-23 14:52
閱讀 3649·2019-08-23 14:39