3.26 實戰智慧合約眾籌2

尹成發表於2018-11-09

在上面我們自己手寫了一個眾籌案例、接下來對案例做一個除錯檢查 
首先我們實現一個ERC20 TOKEN,程式碼如下:

pragma solidity ^0.4.16;
interface tokenRecipient { function receiveApproval(address _from, uint256 _value, address _token, bytes _extraData) public; }
contract TokenERC20 {
    string public name;
    string public symbol;
    uint8 public decimals = 18;  // decimals 可以有的小數點個數,最小的代幣單位。18 是建議的預設值
    uint256 public totalSupply;
    // 用mapping儲存每個地址對應的餘額
    mapping (address => uint256) public balanceOf;
    // 儲存對賬號的控制
    mapping (address => mapping (address => uint256)) public allowance;
    // 事件,用來通知客戶端交易發生
    event Transfer(address indexed from, address indexed to, uint256 value);
    // 事件,用來通知客戶端代幣被消費
    event Burn(address indexed from, uint256 value);
    /**
     * 初始化構造
     */
    function TokenERC20(uint256 initialSupply, string tokenName, string tokenSymbol) public {
        totalSupply = initialSupply * 10 ** uint256(decimals);  // 供應的份額,份額跟最小的代幣單位有關,份額 = 幣數 * 10 ** decimals。
        balanceOf[msg.sender] = totalSupply;                // 建立者擁有所有的代幣
        name = tokenName;                                   // 代幣名稱
        symbol = tokenSymbol;                               // 代幣符號
    }
    /**
     * 代幣交易轉移的內部實現
     */
    function _transfer(address _from, address _to, uint _value) internal {
        // 確保目標地址不為0x0,因為0x0地址代表銷燬
        require(_to != 0x0);
        // 檢查傳送者餘額
        require(balanceOf[_from] >= _value);
        // 確保轉移為正數個
        require(balanceOf[_to] + _value > balanceOf[_to]);
        // 以下用來檢查交易,
        uint previousBalances = balanceOf[_from] + balanceOf[_to];
        // Subtract from the sender
        balanceOf[_from] -= _value;
        // Add the same to the recipient
        balanceOf[_to] += _value;
        Transfer(_from, _to, _value);
        // 用assert來檢查程式碼邏輯。
        assert(balanceOf[_from] + balanceOf[_to] == previousBalances);
    }
    /**
     *  代幣交易轉移
     * 從建立交易者賬號傳送`_value`個代幣到 `_to`賬號
     *
     * @param _to 接收者地址
     * @param _value 轉移數額
     */
    function transfer(address _to, uint256 _value) public {
        _transfer(msg.sender, _to, _value);
    }
    /**
     * 賬號之間代幣交易轉移
     * @param _from 傳送者地址
     * @param _to 接收者地址
     * @param _value 轉移數額
     */
    function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
        require(_value <= allowance[_from][msg.sender]);     // Check allowance
        allowance[_from][msg.sender] -= _value;
        _transfer(_from, _to, _value);
        return true;
    }
    /**
     * 設定某個地址(合約)可以交易者名義花費的代幣數。
     *
     * 允許傳送者`_spender` 花費不多於 `_value` 個代幣
     *
     * @param _spender The address authorized to spend
     * @param _value the max amount they can spend
     */
    function approve(address _spender, uint256 _value) public
        returns (bool success) {
        allowance[msg.sender][_spender] = _value;
        return true;
    }
    /**
     * 設定允許一個地址(合約)以交易者名義可最多花費的代幣數。
     *
     * @param _spender 被授權的地址(合約)
     * @param _value 最大可花費代幣數
     * @param _extraData 傳送給合約的附加資料
     */
    function approveAndCall(address _spender, uint256 _value, bytes _extraData)
        public
        returns (bool success) {
        tokenRecipient spender = tokenRecipient(_spender);
        if (approve(_spender, _value)) {
            spender.receiveApproval(msg.sender, _value, this, _extraData);
            return true;
        }
    }
    /**
     * 銷燬建立者賬戶中指定個代幣
     */
    function burn(uint256 _value) public returns (bool success) {
        require(balanceOf[msg.sender] >= _value);   // Check if the sender has enough
        balanceOf[msg.sender] -= _value;            // Subtract from the sender
        totalSupply -= _value;                      // Updates totalSupply
        Burn(msg.sender, _value);
        return true;
    }
    /**
     * 銷燬使用者賬戶中指定個代幣
     *
     * Remove `_value` tokens from the system irreversibly on behalf of `_from`.
     *
     * @param _from the address of the sender
     * @param _value the amount of money to burn
     */
    function burnFrom(address _from, uint256 _value) public returns (bool success) {
        require(balanceOf[_from] >= _value);                // Check if the targeted balance is enough
        require(_value <= allowance[_from][msg.sender]);    // Check allowance
        balanceOf[_from] -= _value;                         // Subtract from the targeted balance
        allowance[_from][msg.sender] -= _value;             // Subtract from the sender's allowance
        totalSupply -= _value;                              // Update totalSupply
        Burn(_from, _value);
        return true;
    }
}

接下來我們先部署這個合約,該合約我們可以自己傳入發行量、代幣名稱和符號,這個的具體細節在前面已經講到,不再贅述。 
合約部署完成後自己在MetaMask上新增TOKEN 
然後部署我們的眾籌合約,首先我們看看前面講的引數:

  • ifSuccessfulSendTo: 募資成功後的收款方(其實這裡可以預設為合約建立者)
  • fundingGoalInEthers:募資額度, 為了方便我們僅募3個ether
  • durationInMinutes: 募資時間
  • finneyCostOfEachToken: 每個代幣的價格
  • addressOfTokenUsedAsReward: 代幣合約地址。

看看合約部署介面 

 傳入引數後點選”create”,部署合約 

 接下來我們需要等待確認完成 

 

這樣,我們的眾籌合約部署就完成了,然後我們可以通過給收款方轉以太幣來買入眾籌方所發的TOKEN 
先開啟錢包網站:myetherwallet.com 

 然後開始交易 

 傳送交易 

 

上面就是我們的眾籌合約相關部署例項了。

 

 

 

相關文章