3.24 vchain原始碼分析2

尹成發表於2018-11-09

接下來是合約的第二部分,直接上程式碼,註釋都在程式碼中

// Contract to sell and distribute VEN tokens
// 分發VEN 代幣
contract VENSale is Owned{
    /// chart of stage transition
    ///
    /// deploy   initialize      startTime                            endTime                 finalize
    ///                              | <-earlyStageLasts-> |             | <- closedStageLasts -> |
    ///  O-----------O---------------O---------------------O-------------O------------------------O------------>
    ///     Created     Initialized           Early             Normal             Closed            Finalized
    enum Stage {
        NotCreated,
        Created,
        Initialized,
        Early,
        Normal,
        Closed,
        Finalized
    }
    using SafeMath for uint256;
    uint256 public constant totalSupply         = (10 ** 9) * (10 ** 18); // 1 billion VEN, decimals set to 18 // 總量 10億枚
    uint256 constant privateSupply              = totalSupply * 9 / 100;  // 9% for private ICO 私募
    uint256 constant commercialPlan             = totalSupply * 23 / 100; // 23% for commercial plan 企業投資人
    uint256 constant reservedForTeam            = totalSupply * 5 / 100;  // 5% for team // 團隊保留
    uint256 constant reservedForOperations      = totalSupply * 22 / 100; // 22 for operations 持續經營及技術發展+ 商業落地推廣
    // 59%
    uint256 public constant nonPublicSupply     = privateSupply + commercialPlan + reservedForTeam + reservedForOperations; // 非公開銷售 59%
    // 41%
    uint256 public constant publicSupply = totalSupply - nonPublicSupply; // 公開銷售41%
    uint256 public constant officialLimit = 64371825 * (10 ** 18); // 官方銷售總量
    uint256 public constant channelsLimit = publicSupply - officialLimit; // 渠道銷售總量
    // packed to 256bit
    struct SoldOut {
        uint16 placeholder; // placeholder to make struct pre-alloced
        // amount of tdokens officially sol out.
        // max value of 120bit is about 1e36, it's enough for token amount
        uint120 official; // 官方銷售數量
        // 通過渠道銷售的代幣數量
        uint120 channels; // amount of tokens sold out via channels
    }
    SoldOut soldOut;
    uint256 constant venPerEth = 3500;  // normal exchange rate 與以太幣的兌換  1 eth = 3500 ven
    uint256 constant venPerEthEarlyStage = venPerEth + venPerEth * 15 / 100;  // early stage has 15% reward 在早期階段,因為有獎勵 所以 1 eth = 3500 + 3500 * 15% = 4025 ven
    uint constant minBuyInterval = 30 minutes; // each account can buy once in 30 minutes  每個帳戶可以在30分鐘內購買一次
    uint constant maxBuyEthAmount = 30 ether; // 每個賬戶最大購買數量為30個eth等值的ven
    VEN ven; // VEN token contract follows ERC20 standard
    address ethVault; // the account to keep received ether  接收以太幣的賬戶
    address venVault; // the account to keep non-public offered VEN tokens  傳送非公開提供VEN的賬戶
    uint public constant startTime = 1503057600; // time to start sale  眾籌開始時間
    uint public constant endTime = 1504180800;   // tiem to close sale 眾籌結束時間
    uint public constant earlyStageLasts = 3 days; // early bird stage lasts in seconds 早期階段的持續時間
    bool initialized;  // 初始化
    bool finalized; // 結束
    function VENSale() {
        soldOut.placeholder = 1;
    }
    /// @notice calculte exchange rate according to current stage
    /// @return exchange rate. zero if not in sale.
    // 計算當前階段的兌換比例
    function exchangeRate() constant returns (uint256){
        if (stage() == Stage.Early) {
            return venPerEthEarlyStage; // 早期階段的比例
        }
        if (stage() == Stage.Normal) {
            return venPerEth; // 正常階段的比例
        }
        return 0;
    }
    /// @notice for test purpose
    //  區塊產生時間
    function blockTime() constant returns (uint32) {
        return uint32(block.timestamp);
    }
    /// @notice estimate stage
    /// @return current stage
    //  得到當前處於哪一個階段
    function stage() constant returns (Stage) {
        if (finalized) {
            return Stage.Finalized;
        }
        if (!initialized) {
            // deployed but not initialized // 合約剛剛部署
            return Stage.Created;
        }
        // 尚未開始眾籌
        if (blockTime() < startTime) {
            // not started yet
            return Stage.Initialized;
        }
        // 售罄
        if (uint256(soldOut.official).add(soldOut.channels) >= publicSupply) {
            // all sold out
            return Stage.Closed;
        }
        // 眾籌階段
        if (blockTime() < endTime) {
            // in sale
            if (blockTime() < startTime.add(earlyStageLasts)) {
            // early bird stage
                return Stage.Early;
            }
            // normal stage
            return Stage.Normal;
        }
        // closed
        return Stage.Closed;
    }
    // 檢查是否是一個合約地址
    function isContract(address _addr) constant internal returns(bool) {
        uint size;
        if (_addr == 0) return false;
        assembly {
            size := extcodesize(_addr)
        }
        return size > 0;
    }
    /// @notice entry to buy tokens
    function () payable {
        buy();
    }
    /// @notice entry to buy tokens
    // 買幣
    function buy() payable {
        // reject contract buyer to avoid breaking interval limit
        // 禁止合約賬戶購買代幣
        require(!isContract(msg.sender));
        require(msg.value >= 0.01 ether);
        uint256 rate = exchangeRate(); //獲取兌換比例
        // here don't need to check stage. rate is only valid when in sale
        require(rate > 0);
        // each account is allowed once in minBuyInterval
        require(blockTime() >= ven.lastMintedTimestamp(msg.sender) + minBuyInterval);// 指定的時間內只允許買一次
        uint256 requested;
        // and limited to maxBuyEthAmount
        // 限制購買數量
        if (msg.value > maxBuyEthAmount) {
            requested = maxBuyEthAmount.mul(rate); // 超過允許購買數量 , 就使用最大允許購買值乘以兌換率
        } else {
            requested = msg.value.mul(rate);
        }
        uint256 remained = officialLimit.sub(soldOut.official);
        if (requested > remained) { // 要購買的數量 大於剩餘數量
            //exceed remained
            requested = remained;
        }
        uint256 ethCost = requested.div(rate); // 計算花費的以太幣
        if (requested > 0) {
            ven.mint(msg.sender, requested, true, blockTime());
            // transfer ETH to vault
            ethVault.transfer(ethCost); // 轉入以太幣
            soldOut.official = requested.add(soldOut.official).toUINT120(); // 修改官方銷售的數量
            onSold(msg.sender, requested, ethCost);
        }
        uint256 toReturn = msg.value.sub(ethCost); // (簡單來說,此處就是)找零
        if(toReturn > 0) {
            // return over payed ETH
            msg.sender.transfer(toReturn);
        }
    }
    /// @notice returns tokens sold officially
    // 返回正式銷售的代幣
    function officialSold() constant returns (uint256) {
        return soldOut.official;
    }
    /// @notice returns tokens sold via channels
    // 通過渠道銷售的幣
    function channelsSold() constant returns (uint256) {
        return soldOut.channels;
    }
    /// @notice manually offer tokens to channel // 手動為渠道提供token
    function offerToChannel(address _channelAccount, uint256 _venAmount) onlyOwner {
        Stage stg = stage(); // 獲取當前處於哪個階段
        // since the settlement may be delayed, so it's allowed in closed stage
        require(stg == Stage.Early || stg == Stage.Normal || stg == Stage.Closed);
        soldOut.channels = _venAmount.add(soldOut.channels).toUINT120(); // 修改渠道銷售的token數量
        //should not exceed limit  不能超過渠道銷售數量的限制
        require(soldOut.channels <= channelsLimit);
        ven.mint(
            _channelAccount,
            _venAmount,
            true,  // unsold tokens can be claimed by channels portion 未售出的代幣可以通過渠道部分來申領
            blockTime()
        );
        onSold(_channelAccount, _venAmount, 0);
    }
    /// @notice initialize to prepare for sale
    /// @param _ven The address VEN token contract following ERC20 standard
    /// @param _ethVault The place to store received ETH
    /// @param _venVault The place to store non-publicly supplied VEN tokens
    //  初始化
    function initialize(
        VEN _ven, // 合約例項
        address _ethVault,  // 接收買家以太幣的地址
        address _venVault) onlyOwner { // 傳送ven的地址
        require(stage() == Stage.Created); //階段限制
        // ownership of token contract should already be this
        require(_ven.owner() == address(this)); // 所有許可權制
        require(address(_ethVault) != 0); // 不能為空
        require(address(_venVault) != 0);
        ven = _ven;
        ethVault = _ethVault;
        venVault = _venVault;
        // 團隊保留鑄幣
        ven.mint(
            venVault,
            reservedForTeam.add(reservedForOperations),
            false, // team and operations reserved portion can't share unsold tokens
            blockTime()
        );
        // 私募和個人投資人的幣
        ven.mint(
            venVault,
            privateSupply.add(commercialPlan),
            true, // private ICO and commercial plan can share unsold tokens 可以共享未出售的token
            blockTime()
        );
        initialized = true;
        onInitialized();
    }
    /// @notice finalize
    function finalize() onlyOwner {
        // only after closed stage
        require(stage() == Stage.Closed); // 階段限制
        uint256 unsold = publicSupply.sub(soldOut.official).sub(soldOut.channels); // 計算未出售的代幣
        if (unsold > 0) {
            // unsold VEN as bonus
            ven.offerBonus(unsold); // 將未出售的代幣作為獎勵
        }
        ven.seal();
        finalized = true;
        onFinalized();
    }
    event onInitialized(); // 初始化事件
    event onFinalized(); // 完成事件
    event onSold(address indexed buyer, uint256 venAmount, uint256 ethCost); // 事件 表示有人購買ven
}

 

相關文章