本篇內(nèi)容主要講解“Story DAO的白名單和測試方法是什么”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“Story DAO的白名單和測試方法是什么”吧!
成都創(chuàng)新互聯(lián)專注于嘉興企業(yè)網(wǎng)站建設(shè),成都響應(yīng)式網(wǎng)站建設(shè)公司,商城開發(fā)。嘉興網(wǎng)站建設(shè)公司,為嘉興等地區(qū)提供建站服務(wù)。全流程按需制作,專業(yè)設(shè)計,全程項目跟蹤,成都創(chuàng)新互聯(lián)專業(yè)和態(tài)度為您提供的服務(wù)
讓我們用這個骨架創(chuàng)建一個新的合約StoryDao.sol
:
pragma solidity ^0.4.24; import "../node_modules/openzeppelin-solidity/contracts/math/SafeMath.sol"; import "../node_modules/openzeppelin-solidity/contracts/ownership/Ownable.sol"; contract StoryDao is Ownable { using SafeMath for uint256; mapping(address => bool) whitelist; uint256 public whitelistedNumber = 0; mapping(address => bool) blacklist; event Whitelisted(address addr, bool status); event Blacklisted(address addr, bool status); uint256 public daofee = 100; // hundredths of a percent, i.e. 100 is 1% uint256 public whitelistfee = 10000000000000000; // in Wei, this is 0.01 ether event SubmissionCommissionChanged(uint256 newFee); event WhitelistFeeChanged(uint256 newFee); uint256 public durationDays = 21; // duration of story's chapter in days uint256 public durationSubmissions = 1000; // duration of story's chapter in entries function changedaofee(uint256 _fee) onlyOwner external { require(_fee < daofee, "New fee must be lower than old fee."); daofee = _fee; emit SubmissionCommissionChanged(_fee); } function changewhitelistfee(uint256 _fee) onlyOwner external { require(_fee < whitelistfee, "New fee must be lower than old fee."); whitelistfee = _fee; emit WhitelistFeeChanged(_fee); } function lowerSubmissionFee(uint256 _fee) onlyOwner external { require(_fee < submissionZeroFee, "New fee must be lower than old fee."); submissionZeroFee = _fee; emit SubmissionFeeChanged(_fee); } function changeDurationDays(uint256 _days) onlyOwner external { require(_days >= 1); durationDays = _days; } function changeDurationSubmissions(uint256 _subs) onlyOwner external { require(_subs > 99); durationSubmissions = _subs; } }
我們正在導(dǎo)入SafeMath
以便再次進(jìn)行安全計算,但這次我們還使用了Zeppelin的Ownable
合約,該合約允許某人“擁有”故事并執(zhí)行某些僅限管理員的功能。簡單地說我們的StoryDao is Ownable
就夠了;隨時檢查合約,看看它是如何工作的。
我們還使用此合約中的onlyOwner
修飾符。函數(shù)修飾符基本上是函數(shù)擴(kuò)展和插件。onlyOwner
修飾符如下所示:
modifier onlyOwner() { require(msg.sender == owner); _; }
當(dāng)onlyOwner
被添加到一個函數(shù)中時,那個函數(shù)的體被粘貼到_;
所在的部分,并且它比其他的一切內(nèi)容都先執(zhí)行。因此,通過使用此修飾符,該函數(shù)會自動檢查郵件發(fā)件人是否也是合約的所有者,然后照常繼續(xù)(如果是)。如果沒有,它會崩潰。
通過在改變我們的Story DAO的費用和其他參數(shù)的函數(shù)上使用onlyOwner
修飾符,我們確保只有管理員才能進(jìn)行這些更改。
讓我們測試一下初始函數(shù)。
如果文件夾test
不存在,請創(chuàng)建它。然后在其中創(chuàng)建文件TestStoryDao.sol
和TestStoryDao.js
。因為在Truffle中沒有本地方法來測試異常,所以也可以使用以下內(nèi)容創(chuàng)建helpers/expectThrow.js
:
export default async promise => { try { await promise; } catch (error) { const invalidOpcode = error.message.search('invalid opcode') >= 0; const outOfGas = error.message.search('out of gas') >= 0; const revert = error.message.search('revert') >= 0; assert( invalidOpcode || outOfGas || revert, 'Expected throw, got \'' + error + '\' instead', ); return; } assert.fail('Expected throw not received'); };
注意:Solidity測試通常用于測試基于合約的低級函數(shù),即智能合約的內(nèi)部。JS測試通常用于測試合約是否可以與外部進(jìn)行正確的交互,這是我們最終用戶將要做的事情。
在TestStoryDao.sol
,輸入以下內(nèi)容:
pragma solidity ^0.4.24; import "truffle/Assert.sol"; import "truffle/DeployedAddresses.sol"; import "../contracts/StoryDao.sol"; contract TestStoryDao { function testDeploymentIsFine() public { StoryDao sd = StoryDao(DeployedAddresses.StoryDao()); uint256 daofee = 100; // hundredths of a percent, i.e. 100 is 1% uint256 whitelistfee = 10000000000000000; // in Wei, this is 0.01 ether uint256 durationDays = 21; // duration of story's chapter in days uint256 durationSubmissions = 1000; // duration of story's chapter in entries Assert.equal(sd.daofee(), daofee, "Initial DAO fee should be 100"); Assert.equal(sd.whitelistfee(), whitelistfee, "Initial whitelisting fee should be 0.01 ether"); Assert.equal(sd.durationDays(), durationDays, "Initial day duration should be set to 3 weeks"); Assert.equal(sd.durationSubmissions(), durationSubmissions, "Initial submission duration should be set to 1000 entries"); } }
這將檢查StoryDao合約是否正確部署,并提供正確的費用和持續(xù)時間。第一行確保通過從已部署地址列表中讀取它來部署它,并且最后一節(jié)做了一些斷言——檢查聲明是真還是假。在我們的例子中,我們將數(shù)字與已部署合約的初始值進(jìn)行比較。每當(dāng)它為“true”時,Assert.equals
部分將發(fā)出一個“True”的事件,這是Truffle在測試時正在監(jiān)聽的事件。
在TestStoryDao.js
,輸入以下內(nèi)容:
import expectThrow from './helpers/expectThrow'; const StoryDao = artifacts.require("StoryDao"); contract('StoryDao Test', async (accounts) => { it("should make sure environment is OK by checking that the first 3 accounts have over 20 eth", async () =>{ assert.equal(web3.eth.getBalance(accounts[0]).toNumber() > 2e+19, true, "Account 0 has more than 20 eth"); assert.equal(web3.eth.getBalance(accounts[1]).toNumber() > 2e+19, true, "Account 1 has more than 20 eth"); assert.equal(web3.eth.getBalance(accounts[2]).toNumber() > 2e+19, true, "Account 2 has more than 20 eth"); }); it("should make the deployer the owner", async () => { let instance = await StoryDao.deployed(); assert.equal(await instance.owner(), accounts[0]); }); it("should let owner change fee and duration", async () => { let instance = await StoryDao.deployed(); let newDaoFee = 50; let newWhitelistFee = 1e+10; // 1 ether let newDayDuration = 42; let newSubsDuration = 1500; instance.changedaofee(newDaoFee, {from: accounts[0]}); instance.changewhitelistfee(newWhitelistFee, {from: accounts[0]}); instance.changedurationdays(newDayDuration, {from: accounts[0]}); instance.changedurationsubmissions(newSubsDuration, {from: accounts[0]}); assert.equal(await instance.daofee(), newDaoFee); assert.equal(await instance.whitelistfee(), newWhitelistFee); assert.equal(await instance.durationDays(), newDayDuration); assert.equal(await instance.durationSubmissions(), newSubsDuration); }); it("should forbid non-owners from changing fee and duration", async () => { let instance = await StoryDao.deployed(); let newDaoFee = 50; let newWhitelistFee = 1e+10; // 1 ether let newDayDuration = 42; let newSubsDuration = 1500; await expectThrow(instance.changedaofee(newDaoFee, {from: accounts[1]})); await expectThrow(instance.changewhitelistfee(newWhitelistFee, {from: accounts[1]})); await expectThrow(instance.changedurationdays(newDayDuration, {from: accounts[1]})); await expectThrow(instance.changedurationsubmissions(newSubsDuration, {from: accounts[1]})); }); it("should make sure the owner can only change fees and duration to valid values", async () =>{ let instance = await StoryDao.deployed(); let invalidDaoFee = 20000; let invalidDayDuration = 0; let invalidSubsDuration = 98; await expectThrow(instance.changedaofee(invalidDaoFee, {from: accounts[0]})); await expectThrow(instance.changedurationdays(invalidDayDuration, {from: accounts[0]})); await expectThrow(instance.changedurationsubmissions(invalidSubsDuration, {from: accounts[0]})); }) });
為了使我們的測試成功運行,我們還需要告訴Truffle我們想要部署StoryDao——因為它不會為我們做。因此,讓我們在migrations
創(chuàng)建3_deploy_storydao.js
,其內(nèi)容幾乎與我們之前編寫的遷移相同:
var Migrations = artifacts.require("./Migrations.sol"); var StoryDao = artifacts.require("./StoryDao.sol"); module.exports = function(deployer, network, accounts) { if (network == "development") { deployer.deploy(StoryDao, {from: accounts[0]}); } else { deployer.deploy(StoryDao); } };
此時,我們還應(yīng)該在項目文件夾的根目錄中更新(或創(chuàng)建,如果它不存在)package.json
文件,其中包含我們目前所需的依賴項,并且可能在不久的將來需要:
{ "name": "storydao", "devDependencies": { "babel-preset-es2015": "^6.18.0", "babel-preset-stage-2": "^6.24.1", "babel-preset-stage-3": "^6.17.0", "babel-polyfill": "^6.26.0", "babel-register": "^6.23.0", "dotenv": "^6.0.0", "truffle": "^4.1.12", "openzeppelin-solidity": "^1.10.0", "openzeppelin-solidity-metadata": "^1.2.0", "openzeppelin-zos": "", "truffle-wallet-provider": "^0.0.5", "ethereumjs-wallet": "^0.6.0", "web3": "^1.0.0-beta.34", "truffle-assertions": "^0.3.1" } }
和.babelrc
文件的內(nèi)容:
{ "presets": ["es2015", "stage-2", "stage-3"] }
我們還需要在我們的Truffle配置中要求Babel,因此它知道它應(yīng)該在編譯時使用它。
注意:Babel是NodeJS的一個附加組件,它允許我們在當(dāng)前一代NodeJS中使用下一代JavaScript,因此我們可以編寫諸如import
。如果這超出了你的理解范圍,只需忽略它,然后只需逐字粘貼即可。在以這種方式安裝后,你可能永遠(yuǎn)不必再處理這個問題。
require('dotenv').config(); ================== ADD THESE TWO LINES ================ require('babel-register'); require('babel-polyfill'); ======================================================= const WalletProvider = require("truffle-wallet-provider"); const Wallet = require('ethereumjs-wallet'); // ...
現(xiàn)在,終于進(jìn)行truffle test
。輸出應(yīng)該類似于這個:
有關(guān)測試的更多信息,請參閱本教程,該教程專門用于測試智能合約。
在本課程的后續(xù)部分中,我們將跳過測試,因為輸入它們會使教程太長,但請參考項目的最終源代碼來檢查它們。我們剛剛完成的過程已經(jīng)設(shè)置了測試環(huán)境,因此你可以在進(jìn)一步設(shè)置的情況下編寫測試。
現(xiàn)在讓我們構(gòu)建一個白名單機(jī)制,讓用戶參與構(gòu)建Story。將以下函數(shù)框架添加到StoryDao.sol
:
function whitelistAddress(address _add) public payable { // whitelist sender if enough money was sent } function() external payable { // if not whitelisted, whitelist if paid enough // if whitelisted, but X tokens at X price for amount }
未命名的函數(shù)function()
被稱為回調(diào)函數(shù),這是在沒有特定指令的情況下將錢發(fā)送到此合約時被調(diào)用的函數(shù)(即,沒有專門調(diào)用其他函數(shù))。這可以讓人們加入StoryDao,只需將以太發(fā)送到DAO并立即將其列入白名單,或者購買代幣,具體取決于它們是否已經(jīng)列入白名單。
whitelistSender
功能用于白名單,可以直接調(diào)用,但是如果發(fā)送方尚未列入白名單,我們將確保當(dāng)收到一些以太時,后備功能會自動調(diào)用它。whitelistAddress
函數(shù)被聲明為public
因為它也應(yīng)該可以從其他合約中調(diào)用,并且回調(diào)函數(shù)是external
函數(shù),因為money
將僅從外部地址轉(zhuǎn)到此地址。調(diào)用此合約的合約可以直接輕松調(diào)用所需的功能。
讓我們首先處理回調(diào)函數(shù)。
function() external payable { if (!whitelist[msg.sender]) { whitelistAddress(msg.sender); } else { // buyTokens(msg.sender, msg.value); } }
我們檢查發(fā)件人是否已經(jīng)在白名單中,并將調(diào)用委托給whitelistAddress
函數(shù)。請注意,我們已經(jīng)注釋掉了buyTokens
函數(shù),因為我們還沒有它。
接下來,讓我們處理白名單。
function whitelistAddress(address _add) public payable { require(!whitelist[_add], "Candidate must not be whitelisted."); require(!blacklist[_add], "Candidate must not be blacklisted."); require(msg.value >= whitelistfee, "Sender must send enough ether to cover the whitelisting fee."); whitelist[_add] = true; whitelistedNumber++; emit Whitelisted(_add, true); if (msg.value > whitelistfee) { // buyTokens(_add, msg.value.sub(whitelistfee)); } }
請注意,此函數(shù)接受地址作為參數(shù),并且不從消息中提取它(來自交易)。如果有人無法承擔(dān)加入DAO的費用,這還有一個額外的好處,即人們可以將其他人列入白名單。
我們通過一些健壯性檢查啟動該功能:發(fā)件人不得列入白名單或列入黑名單(禁止),并且必須已發(fā)送足夠的費用以支付費用。如果這些條件令人滿意,則將地址添加到白名單中,發(fā)出白名單事件,最后,如果發(fā)送的以太數(shù)量大于覆蓋白名單費用所需的以太數(shù)量,則剩余部分用于買這些代幣。
注意:我們使用sub
而不是-
來減,因為這是一個安全計算的SafeMath
函數(shù)。
用戶現(xiàn)在可以將自己或其他人列入白名單,只要他們向StoryDao合約發(fā)送0.01以太或更多。
到此,相信大家對“Story DAO的白名單和測試方法是什么”有了更深的了解,不妨來實際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!
分享名稱:StoryDAO的白名單和測試方法是什么
文章來源:http://jinyejixie.com/article48/gpsdep.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供做網(wǎng)站、網(wǎng)站排名、網(wǎng)站改版、全網(wǎng)營銷推廣、定制開發(fā)、虛擬主機(jī)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)