中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Story DAO的白名單和測試方法是什么

發布時間:2022-01-15 14:34:57 來源:億速云 閱讀:133 作者:iii 欄目:互聯網科技

本篇內容主要講解“Story DAO的白名單和測試方法是什么”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“Story DAO的白名單和測試方法是什么”吧!

合約大綱

讓我們用這個骨架創建一個新的合約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;
    }
}

我們正在導入SafeMath以便再次進行安全計算,但這次我們還使用了Zeppelin的Ownable合約,該合約允許某人“擁有”故事并執行某些僅限管理員的功能。簡單地說我們的StoryDao is Ownable就夠了;隨時檢查合約,看看它是如何工作的。

我們還使用此合約中的onlyOwner修飾符。函數修飾符基本上是函數擴展和插件。onlyOwner修飾符如下所示:

modifier onlyOwner() {
  require(msg.sender == owner);
  _;
}

onlyOwner被添加到一個函數中時,那個函數的體被粘貼到_;所在的部分,并且它比其他的一切內容都先執行。因此,通過使用此修飾符,該函數會自動檢查郵件發件人是否也是合約的所有者,然后照常繼續(如果是)。如果沒有,它會崩潰。

通過在改變我們的Story DAO的費用和其他參數的函數上使用onlyOwner修飾符,我們確保只有管理員才能進行這些更改。

測試

讓我們測試一下初始函數。

如果文件夾test不存在,請創建它。然后在其中創建文件TestStoryDao.solTestStoryDao.js。因為在Truffle中沒有本地方法來測試異常,所以也可以使用以下內容創建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測試通常用于測試基于合約的低級函數,即智能合約的內部。JS測試通常用于測試合約是否可以與外部進行正確的交互,這是我們最終用戶將要做的事情。

TestStoryDao.sol,輸入以下內容:

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合約是否正確部署,并提供正確的費用和持續時間。第一行確保通過從已部署地址列表中讀取它來部署它,并且最后一節做了一些斷言——檢查聲明是真還是假。在我們的例子中,我們將數字與已部署合約的初始值進行比較。每當它為“true”時,Assert.equals部分將發出一個“True”的事件,這是Truffle在測試時正在監聽的事件。

TestStoryDao.js,輸入以下內容:

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創建3_deploy_storydao.js,其內容幾乎與我們之前編寫的遷移相同:

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);
  }
};

此時,我們還應該在項目文件夾的根目錄中更新(或創建,如果它不存在)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文件的內容:

{
  "presets": ["es2015", "stage-2", "stage-3"]
}

我們還需要在我們的Truffle配置中要求Babel,因此它知道它應該在編譯時使用它。

注意:Babel是NodeJS的一個附加組件,它允許我們在當前一代NodeJS中使用下一代JavaScript,因此我們可以編寫諸如import。如果這超出了你的理解范圍,只需忽略它,然后只需逐字粘貼即可。在以這種方式安裝后,你可能永遠不必再處理這個問題。

require('dotenv').config();

================== ADD THESE TWO LINES ================
require('babel-register');
require('babel-polyfill');
=======================================================

const WalletProvider = require("truffle-wallet-provider");
const Wallet = require('ethereumjs-wallet');

// ...

現在,終于進行truffle test。輸出應該類似于這個:

Story DAO的白名單和測試方法是什么

有關測試的更多信息,請參閱本教程,該教程專門用于測試智能合約。

在本課程的后續部分中,我們將跳過測試,因為輸入它們會使教程太長,但請參考項目的最終源代碼來檢查它們。我們剛剛完成的過程已經設置了測試環境,因此你可以在進一步設置的情況下編寫測試。

白名單

現在讓我們構建一個白名單機制,讓用戶參與構建Story。將以下函數框架添加到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
}

未命名的函數function()被稱為回調函數,這是在沒有特定指令的情況下將錢發送到此合約時被調用的函數(即,沒有專門調用其他函數)。這可以讓人們加入StoryDao,只需將以太發送到DAO并立即將其列入白名單,或者購買代幣,具體取決于它們是否已經列入白名單。

whitelistSender功能用于白名單,可以直接調用,但是如果發送方尚未列入白名單,我們將確保當收到一些以太時,后備功能會自動調用它。whitelistAddress函數被聲明為public因為它也應該可以從其他合約中調用,并且回調函數是external函數,因為money將僅從外部地址轉到此地址。調用此合約的合約可以直接輕松調用所需的功能。

讓我們首先處理回調函數。

function() external payable {

    if (!whitelist[msg.sender]) {
        whitelistAddress(msg.sender);
    } else {
        // buyTokens(msg.sender, msg.value);
    }
}

我們檢查發件人是否已經在白名單中,并將調用委托給whitelistAddress函數。請注意,我們已經注釋掉了buyTokens函數,因為我們還沒有它。

接下來,讓我們處理白名單。

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));
    }
}

請注意,此函數接受地址作為參數,并且不從消息中提取它(來自交易)。如果有人無法承擔加入DAO的費用,這還有一個額外的好處,即人們可以將其他人列入白名單。

我們通過一些健壯性檢查啟動該功能:發件人不得列入白名單或列入黑名單(禁止),并且必須已發送足夠的費用以支付費用。如果這些條件令人滿意,則將地址添加到白名單中,發出白名單事件,最后,如果發送的以太數量大于覆蓋白名單費用所需的以太數量,則剩余部分用于買這些代幣。

注意:我們使用sub而不是-來減,因為這是一個安全計算的SafeMath函數。

用戶現在可以將自己或其他人列入白名單,只要他們向StoryDao合約發送0.01以太或更多。

到此,相信大家對“Story DAO的白名單和測試方法是什么”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

德钦县| 巴青县| 洛南县| 宁蒗| 都安| 杂多县| 东城区| 呼和浩特市| 武平县| 浙江省| 长白| 峨眉山市| 钦州市| 涟水县| 邛崃市| 武平县| 西藏| 荆州市| 辽源市| 嘉义市| 鹤壁市| 澄江县| 秦皇岛市| 灵宝市| 贞丰县| 玉树县| 青海省| 吉木萨尔县| 东海县| 政和县| 文成县| 大石桥市| 胶州市| 土默特右旗| 黎城县| 手游| 锦屏县| 江西省| 英超| 方正县| 太保市|