3.23 vchain原始碼分析1

尹成發表於2018-11-09

在做vechain智慧合約原始碼分析之前,我們先來看一下它的簡介 
一、專案名稱 
VeChain(VEN)

二、專案定位 
全球領先的區塊鏈商品和資訊平臺

三、專案簡評 
專案旨在解決商業社會中產品的資訊和信任問題,利用區塊鏈做高附加值產品的防偽追朔系統,基於此打造信任商業的生態體系。

四、專案願景 
vechain的目標其實就是應用區塊鏈技術構造一個既可以自我迴圈、也可以向外擴充的可信任分散式商業生態環境。

接下來 我們直接通過它的智慧合約程式碼來仔細瞭解一下它的內部實現細節 

首先是第一部分合約程式碼:

pragma solidity ^0.4.11;
// 許可權控制合約
contract Owned {
    address public owner;
    function Owned() {
        owner = msg.sender;
    }
    // 許可權控制修飾符
    modifier onlyOwner() {
        require(msg.sender == owner);
        _;
    }
    function setOwner(address _newOwner) onlyOwner {
        owner = _newOwner;
    }
}
/**
 * @title SafeMath
 * @dev Math operations with safety checks that throw on error
 */
// 數學安全函式
library SafeMath {
    function mul(uint256 a, uint256 b) internal constant returns (uint256) {
        uint256 c = a * b;
        assert(a == 0 || c / a == b); // 判斷 a不能為0 C/A不能等於b(防止造成gas浪費)
        return c;
    }
    function div(uint256 a, uint256 b) internal constant returns (uint256) {
        // assert(b > 0); // Solidity automatically throws when dividing by 0
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold
        return c;
    }
    function sub(uint256 a, uint256 b) internal constant returns (uint256) {
        assert(b <= a); // 預防溢位
        return a - b;
    }
    function add(uint256 a, uint256 b) internal constant returns (uint256) {
        uint256 c = a + b;
        assert(c >= a); // 節省gas
        return c;
    }
    function toUINT112(uint256 a) internal constant returns(uint112) {
        assert(uint112(a) == a); // 預防溢位
        return uint112(a);
    }
    function toUINT120(uint256 a) internal constant returns(uint120) {
        assert(uint120(a) == a); // 預防溢位
        return uint120(a);
    }
    function toUINT128(uint256 a) internal constant returns(uint128) {
        assert(uint128(a) == a); // 預防溢位
        return uint128(a);
    }
}
// Abstract contract for the full ERC 20 Token standard
// https://github.com/ethereum/EIPs/issues/20
// 抽象合約
contract Token {
    /* This is a slight change to the ERC20 base standard.
    function totalSupply() constant returns (uint256 supply);
    is replaced with:
    uint256 public totalSupply;
    This automatically creates a getter function for the totalSupply.
    This is moved to the base contract since public getter functions are not
    currently recognised as an implementation of the matching abstract
    function by the compiler.
    */
    /// total amount of tokens
    //uint256 public totalSupply;
    function totalSupply() constant returns (uint256 supply); // 總髮行量
    /// @param _owner The address from which the balance will be retrieved
    /// @return The balance
    function balanceOf(address _owner) constant returns (uint256 balance); // 查詢餘額
    /// @notice send `_value` token to `_to` from `msg.sender`
    /// @param _to The address of the recipient
    /// @param _value The amount of token to be transferred
    /// @return Whether the transfer was successful or not
    function transfer(address _to, uint256 _value) returns (bool success); // 轉賬
    /// @notice send `_value` token to `_to` from `_from` on the condition it is approved by `_from`
    /// @param _from The address of the sender
    /// @param _to The address of the recipient
    /// @param _value The amount of token to be transferred
    /// @return Whether the transfer was successful or not
    function transferFrom(address _from, address _to, uint256 _value) returns (bool success); // 指定源地址轉向指定目標地址
    /// @notice `msg.sender` approves `_addr` to spend `_value` tokens
    /// @param _spender The address of the account able to transfer the tokens
    /// @param _value The amount of wei to be approved for transfer
    /// @return Whether the approval was successful or not
    function approve(address _spender, uint256 _value) returns (bool success); // 允許量值設定
    /// @param _owner The address of the account owning tokens
    /// @param _spender The address of the account able to transfer the tokens
    /// @return Amount of remaining tokens allowed to spent
    function allowance(address _owner, address _spender) constant returns (uint256 remaining); // 允許指定地址提取的餘額
    event Transfer(address indexed _from, address indexed _to, uint256 _value); // 轉賬事件
    event Approval(address indexed _owner, address indexed _spender, uint256 _value); // approve 事件
}
/// VEN token, ERC20 compliant
contract VEN is Token, Owned {
    using SafeMath for uint256; // 附著庫使用
    string public constant name    = "VeChain Token";  //The Token's name 代幣名稱
    uint8 public constant decimals = 18;               //Number of decimals of the smallest unit 精度
    string public constant symbol  = "VEN";            //An identifier 標識(符號)
    // packed to 256bit to save gas usage.
    // 打包為256位以節省gas
    struct Supplies {
        // uint128's max value is about 3e38.
        // it's enough to present amount of tokens
        uint128 total; // 總量
        uint128 rawTokens;
    }
    Supplies supplies;
    // Packed to 256bit to save gas usage.
    // 打包成256位以節省gas
    struct Account {
        // uint112's max value is about 5e33.
        // it's enough to present amount of tokens
        uint112 balance;
        // raw token can be transformed into balance with bonus
        // 原始token  可以轉移到balance中
        uint112 rawTokens;
        // safe to store timestamp
        uint32 lastMintedTimestamp; // 區塊時間
    }
    // Balances for each account
    mapping(address => Account) accounts; // 指定地址的餘額
    // Owner of account approves the transfer of an amount to another account
    // 賬戶所有者所允許轉到另一個地址的金額
    mapping(address => mapping(address => uint256)) allowed;
    // bonus that can be shared by raw tokens
    uint256 bonusOffered; // 獎勵
    // Constructor
    function VEN() {
    }
    // 總髮行量
    function totalSupply() constant returns (uint256 supply){
        return supplies.total;
    }
    // Send back ether sent to me
    // 回退函式
    function () {
        revert(); // 將ether返還
    }
    // If sealed, transfer is enabled and mint is disabled
    function isSealed() constant returns (bool) {
        return owner == 0;
    }
    // 最近一次區塊生成時間
    function lastMintedTimestamp(address _owner) constant returns(uint32) {
        return accounts[_owner].lastMintedTimestamp;
    }
    // Claim bonus by raw tokens
    function claimBonus(address _owner) internal{
        require(isSealed());
        if (accounts[_owner].rawTokens != 0) {
            uint256 realBalance = balanceOf(_owner); // 真實的餘額
            // 獎勵
            uint256 bonus = realBalance
            .sub(accounts[_owner].balance)
            .sub(accounts[_owner].rawTokens); // 獲取獎勵
            accounts[_owner].balance = realBalance.toUINT112();
            accounts[_owner].rawTokens = 0;
            if(bonus > 0){
                Transfer(this, _owner, bonus);
            }
        }
    }
    // What is the balance of a particular account?
    function balanceOf(address _owner) constant returns (uint256 balance) {
        if (accounts[_owner].rawTokens == 0)
            return accounts[_owner].balance;
        if (bonusOffered > 0) {
            uint256 bonus = bonusOffered
            .mul(accounts[_owner].rawTokens)
            .div(supplies.rawTokens);
            return bonus.add(accounts[_owner].balance)
            .add(accounts[_owner].rawTokens);
        }
        return uint256(accounts[_owner].balance)
        .add(accounts[_owner].rawTokens);
    }
    // Transfer the balance from owner's account to another account
    // 轉賬
    function transfer(address _to, uint256 _amount) returns (bool success) {
        require(isSealed());
        // implicitly claim bonus for both sender and receiver
        claimBonus(msg.sender);
        claimBonus(_to);
        // according to VEN's total supply, never overflow here
        if (accounts[msg.sender].balance >= _amount
        && _amount > 0) {
            accounts[msg.sender].balance -= uint112(_amount);
            accounts[_to].balance = _amount.add(accounts[_to].balance).toUINT112();
            Transfer(msg.sender, _to, _amount);
            return true;
        } else {
            return false;
        }
    }
    // Send _value amount of tokens from address _from to address _to
    // The transferFrom method is used for a withdraw workflow, allowing contracts to send
    // tokens on your behalf, for example to "deposit" to a contract address and/or to charge
    // fees in sub-currencies; the command should fail unless the _from account has
    // deliberately authorized the sender of the message via some mechanism; we propose
    // these standardized APIs for approval:
    function transferFrom(
    address _from,
    address _to,
    uint256 _amount
    ) returns (bool success) {
        require(isSealed());
        // implicitly claim bonus for both sender and receiver
        claimBonus(_from);
        claimBonus(_to);
        // according to VEN's total supply, never overflow here
        if (accounts[_from].balance >= _amount
            && allowed[_from][msg.sender] >= _amount
            && _amount > 0) {
            accounts[_from].balance -= uint112(_amount);
            allowed[_from][msg.sender] -= _amount;
            accounts[_to].balance = _amount.add(accounts[_to].balance).toUINT112();
            Transfer(_from, _to, _amount);
            return true;
        } else {
            return false;
        }
    }
    // Allow _spender to withdraw from your account, multiple times, up to the _value amount.
    // If this function is called again it overwrites the current allowance with _value.
    function approve(address _spender, uint256 _amount) returns (bool success) {
        allowed[msg.sender][_spender] = _amount;
        Approval(msg.sender, _spender, _amount);
        return true;
    }
    /* Approves and then calls the receiving contract */
    function approveAndCall(address _spender, uint256 _value, bytes _extraData) returns (bool success) {
        allowed[msg.sender][_spender] = _value;
        Approval(msg.sender, _spender, _value);
        //call the receiveApproval function on the contract you want to be notified. This crafts the function signature manually so one doesn't have to include a contract in here just for this.
        //receiveApproval(address _from, uint256 _value, address _tokenContract, bytes _extraData)
        //it is assumed that when does this that the call *should* succeed, otherwise one would use vanilla approve instead.
        //if(!_spender.call(bytes4(bytes32(sha3("receiveApproval(address,uint256,address,bytes)"))), msg.sender, _value, this, _extraData)) { revert(); }
        ApprovalReceiver(_spender).receiveApproval(msg.sender, _value, this, _extraData);
        return true;
    }
    function allowance(address _owner, address _spender) constant returns (uint256 remaining) {
        return allowed[_owner][_spender];
    }
    // Mint tokens and assign to some one  鑄幣
    function mint(address _owner, uint256 _amount, bool _isRaw, uint32 timestamp) onlyOwner{
        if (_isRaw) {
            accounts[_owner].rawTokens = _amount.add(accounts[_owner].rawTokens).toUINT112();
            supplies.rawTokens = _amount.add(supplies.rawTokens).toUINT128();
        } else {
            accounts[_owner].balance = _amount.add(accounts[_owner].balance).toUINT112();
        }
        accounts[_owner].lastMintedTimestamp = timestamp;
        supplies.total = _amount.add(supplies.total).toUINT128();
        Transfer(0, _owner, _amount);
    }
    // Offer bonus to raw tokens holder 給代幣持有者提供獎勵
    function offerBonus(uint256 _bonus) onlyOwner {
        bonusOffered = bonusOffered.add(_bonus);
        supplies.total = _bonus.add(supplies.total).toUINT128();
        Transfer(0, this, _bonus);
    }
    // Set owner to zero address, to disable mint, and enable token transfer
    function seal() onlyOwner {
        setOwner(0);
    }
}
contract ApprovalReceiver {
    function receiveApproval(address _from, uint256 _value, address _tokenContract, bytes _extraData);
}

 

相關文章