建立本身的加密貨幣MNC——以太坊代幣(二) 建立本身的區塊鏈遊戲SLOT——以太坊代幣(三)

建立一個基於以太坊平臺的分成幣MNC,根據持有的代幣數量,進行分成的算法。github地址:html

https://github.com/lxr1907/MNCgit

1.使用以太坊根據比例換購token MNCgithub

2.按期根據使用用戶資金購買的礦機挖ETH,打入該合約,觸發分成方法根據token持有比例分成算法

3.衰減,因爲礦機有折舊衰減損壞的機率,token會隨着持有時間而衰減。數組

代碼以下app

pragma solidity ^0.4.19;
contract owned {
    address public owner;
    function owned() public {
        owner = msg.sender;
    }
    modifier onlyOwner {
        require(msg.sender == owner);
        _;
    }
    function transferOwnership(address newOwner) onlyOwner public {
        owner = newOwner;
    }
}

contract LxrContract is owned{
    struct miner{
        //MNC餘額
        uint256 balance;
        //挖礦份額
        uint256 mining;
        //上一次分成,衰減日期
        uint256 lastDate;
        //上一次收益
        uint256 lastBonus;
    }
    //虛擬幣名稱
    string public name;
    //虛擬幣名稱縮寫
    string public symbol;
    //18 decimals 極力推薦使用默認值,儘可能別改
    uint8 public constant decimals = 18;
    //和以太坊兌換的匯率
    uint32 public ethExchangeRate = 1000;
    //總髮行
    uint256 public totalSupply;
    //創始人保留百分比
    uint8  constant ownerInitial=10;
    //合約擁有者
    address public owner;
    //建立全部帳戶餘額數組
    mapping (address => miner) public miners;
    //挖礦須要募集的挖礦資金,100個eth,後續能夠增長
    uint256 public collectAmountLeft=ethExchangeRate*100;
    //0.01個ETH起計算挖礦收益
    uint256  startMiningMin=ethExchangeRate/100;
    //挖礦人地址數組
    address[]  minersArray;
    //分成日期
    uint256 public bonusTimePoint;
    //分成歷史總數
    uint256 public bonusTotal;
    //階段分成累計數,分成後清零
    uint256 public bonusPeriodCumulative;
    //每日折舊率千分比,例如每日千分之2,一年後48.15%,3,一年後剩餘33%,4一年後23.15%
    uint16 depreciationRate=3;
    //每次折舊時間,測試狀況下設置爲1分鐘以便調試
    uint256 depreciationTime=1 minutes;
    //從挖礦帳戶提現手續費百分比
    uint miningDepositFee=30;
    // 在區塊鏈上建立一個公共事件,它觸發就會通知全部客戶端
    event Transfer(address indexed from, address indexed to, uint256 value);
    event BalanceToMine(address indexed from, uint256 value);
    event MiningDeposit(address indexed from, uint256 value, uint256 fee);
    event TransferMining(address indexed from,address indexed to, uint256 value);
    event Bonus(address indexed to, uint256 value);
    event Burn(address indexed from, uint256 value);
    /**
     * 初始化合約,將最初的令牌中的一部分打入建立者的帳戶中
     * @param initialSupply 初始發行量
     * @param tokenName 虛擬幣名稱
     * @param tokenSymbol 虛擬幣名稱縮寫
     */
    function LxrContract(
        uint256 initialSupply,
        string tokenName,
        string tokenSymbol
    ) public {
        //初始化合約全部人
        owner=msg.sender;
        //合約帳戶餘額初始
        _mintToken(this,initialSupply-initialSupply * ownerInitial/100);
        //全部人帳戶餘額初始
        _mintToken(owner,initialSupply * ownerInitial/100);
        // 設置顯示名稱
        name = tokenName;     
        // 設置顯示縮寫,例如比特幣是BTC
        symbol = tokenSymbol;               
        //初始化分成時間點
        bonusTimePoint=now/depreciationTime;
    }

    /**
     * 內部轉帳,只能被該合約調用
     */
    function _transfer(address _from, address _to, uint _value) internal {
        // 檢查發送者是否擁有足夠的幣
        require(miners[_from].balance >= _value);
        // 檢查越界
        require(miners[_to].balance + _value > miners[_to].balance);
        // 從發送者扣幣
        miners[_from].balance -= _value;
        // 給接收者加相同數量幣
        miners[_to].balance += _value;
        //通知
        Transfer(_from, _to, _value);
    }
    /**
     * 帳戶餘額兌換挖礦份額
     */
    function balanceToMining( uint256 _value) public {
        //檢查挖礦募集剩餘
        require(collectAmountLeft > 0);
        require(miners[msg.sender].balance > 0);
        uint256 effectValue=_value;
        //傳0或不傳則全部餘額兌換挖礦份額
        if(effectValue==0){
            effectValue=miners[msg.sender].balance/(10**uint256(decimals));
        }
        // 檢查越界
        require(miners[msg.sender].mining + effectValue > miners[msg.sender].mining);
        // 檢查發送者是否擁有足夠的幣
        if(miners[msg.sender].balance < effectValue){
            effectValue=miners[msg.sender].balance/(10**uint256(decimals));
        }
        //檢查挖礦募集剩餘是否足夠,不足只轉一部分
        if(collectAmountLeft < _value){
            effectValue=collectAmountLeft;
        }
        //帳戶ETH餘額不足,沒法投資
        if(this.balance<effectValue* 10 ** uint256(decimals)/ethExchangeRate){
            return;
        }
        //若是不存在,將該挖礦地址加入數組,用於之後遍歷訪問
        addToMinersArray(msg.sender);
        // 從餘額銷燬
        burn(msg.sender,effectValue);
        // 給挖礦帳戶加相同數量幣
        miners[msg.sender].mining += effectValue* 10 ** uint256(decimals);
        //募集剩餘資金減小
        collectAmountLeft -=effectValue;
        //將挖礦所需以太坊轉到擁有者帳戶,以便全部者使用這些eth購買礦機挖礦
        owner.transfer(effectValue* 10 ** uint256(decimals)/ethExchangeRate);
        //通知
        BalanceToMine(msg.sender, effectValue);
    }
    /**
     * 
     * 將挖礦份額轉換爲帳戶餘額,須要按百分比支付手續費
     * 
     * @param _value 提出金額
     */
    function miningDeposit( uint256 _value) public {
        uint depositFee=_value* 10 ** uint256(decimals)*miningDepositFee/100; 
        uint depositValue=_value* 10 ** uint256(decimals);
        // 檢查發送者是否擁有足夠的幣
        require(miners[msg.sender].mining >= depositValue);
        // 檢查越界
        require(miners[msg.sender].balance + depositValue > miners[msg.sender].balance);
        // 從挖礦餘額扣除
        miners[msg.sender].mining -= depositValue;
        //挖礦餘額剩餘爲0,所有提現,則時間重置
        if(miners[msg.sender].mining==0){
            miners[msg.sender].lastDate=0;
        }
        //給帳戶加相同數量幣,扣除必定百分比手續費
        miners[msg.sender].balance += depositValue-depositFee;
        //將手續費支付給合約管理員
        miners[owner].balance += depositFee;
        //通知
        MiningDeposit(msg.sender, depositValue,depositFee);
    }
    //將該挖礦地址加入數組
    function addToMinersArray(address _miner) internal{
        //若是不存在,將該挖礦地址加入數組,用於之後遍歷訪問
        bool hasAdd=false;
        for (uint i = 0; i < minersArray.length; i++) {
            if(minersArray[i]==_miner){
                hasAdd=true;
                break;
            }
        }
        if(!hasAdd){
            minersArray.push(_miner);   
        }
    }
    /**
     * 將挖礦份額轉讓
     */
    function transferMining(address _to, uint256 _value)  public {
         // 檢查發送者是否擁有足夠的幣
        require(miners[msg.sender].mining >= _value);
        // 檢查越界
        require(miners[_to].mining + _value > miners[_to].mining);
        //將該挖礦地址加入數組
        addToMinersArray(_to);
        // 從發送者扣幣
        miners[msg.sender].mining -= _value;
        // 給接收者加相同數量幣
        miners[_to].mining += _value;
        TransferMining(msg.sender,_to,  _value);
    }
    /**
     *計算總挖礦份額 
     */
    function getMiningAmountTotal() public view returns ( uint256 _totalMinigAmount){
        for (uint i = 0; i < minersArray.length; i++) {
            uint256 miningAmount = miners[minersArray[i]].mining;
            _totalMinigAmount += miningAmount;
        }
        _totalMinigAmount=_totalMinigAmount/(10**uint256(decimals));
    }
    /**
     *根據挖礦份額給每一個人分成 ,匿名方法,直接轉帳觸發
     * bonusMNCtoMiner
     */
    function () payable public {
        //階段收益MNC
        bonusPeriodCumulative += msg.value*ethExchangeRate;
        require(bonusPeriodCumulative>0);
        //該階段已經分成過,只累加分成數量
        if(bonusTimePoint>=now/depreciationTime){
            return;
        }
        //更新分成時間點
        bonusTimePoint=now/depreciationTime;
        uint256 totalMinigAmount=getMiningAmountTotal();
        if(totalMinigAmount==0){
            return;
        }
        //加發行量
        _mintToken(this,bonusPeriodCumulative/(10**uint256(decimals)));
        //總歷史收益增長
        bonusTotal += bonusPeriodCumulative;
        //計算每一個人的收益
        for (uint i = 0; i < minersArray.length; i++) {
            uint256 miningAmount = miners[minersArray[i]].mining/(10**uint256(decimals));
            if(miningAmount<startMiningMin){
                continue;
            }
             //礦機折舊衰減
            if(miners[minersArray[i]].lastDate==0){
                //第一次不折舊,記錄時間
                miners[minersArray[i]].lastDate=now/depreciationTime;
                //第一次也不分成
                continue;
            }else{
                //計算出衰減段數
                uint256 depreciationPeriods=now/depreciationTime-miners[minersArray[i]].lastDate;
                //每段衰減一次
                for(uint m=0;m<depreciationPeriods;m++)
                miners[minersArray[i]].mining=miners[minersArray[i]].mining* (1000-depreciationRate)/1000;
                //更新時間
                miners[minersArray[i]].lastDate=now/depreciationTime;
            }
            //分成數量
            uint256 oneBonus = bonusPeriodCumulative*miningAmount/totalMinigAmount;
            miners[minersArray[i]].lastBonus=oneBonus;
        }
        //階段收益清零
        bonusPeriodCumulative=0;
         //發放收益
        for (uint j = 0; j < minersArray.length; j++) {
            bonusToken(minersArray[j]);
        }
    }
    /**
     *獎勵挖礦收益MNC
     * 
     */
    function bonusToken(address _to) internal{
        miners[_to].balance+= miners[_to].lastBonus ;
        Bonus(_to, miners[_to].lastBonus*(10**uint256(decimals)));
    }
    /**
     * 發送MNC
     *
     * 從你的帳戶發送個`_value` 令牌到 `_to` 
     *
     * @param _to 接收地址
     * @param _value 發送數量
     */
    function transfer(address _to, uint256 _value) public {
        _transfer(msg.sender, _to, _value);
    }
    /**
     *增發MNC
     * 
     */
    function _mintToken(address _to, uint256 mintedAmount) internal{
        totalSupply += mintedAmount*(10**uint256(decimals));
        miners[_to].balance+= mintedAmount*(10**uint256(decimals));
        Transfer(0, _to, mintedAmount*(10**uint256(decimals)));
    }
    //增發MNC
    function MintToken( uint256 mintedAmount) onlyOwner public{
        _mintToken(this,mintedAmount);
    }
    /**
     *銷燬MNC
     * 
     */
    function burn( address _from,uint256 mintedAmount) internal{
        totalSupply -= mintedAmount*(10**uint256(decimals));
        miners[_from].balance-= mintedAmount*(10**uint256(decimals));
        Burn(_from, mintedAmount*(10**uint256(decimals)));
    }
    /**
     * 
     *增長募集金額
     * @param amount 須要的MNC數量
     */
    function addCollection( uint256 amount) onlyOwner  public{
        collectAmountLeft += amount;
    }
   
    /// 使用以太坊購買token
    function buy() payable public {
        uint amount = msg.value;
        //合約餘額充足         
        require(miners[this].balance>=amount * ethExchangeRate);
        _transfer( this,msg.sender, amount * ethExchangeRate);
    }
    //出售token換回以太坊
    function sell(uint256 amount)  public {
        _transfer(msg.sender, this, amount* 10 ** uint256(decimals));             
        msg.sender.transfer(amount* 10 ** uint256(decimals)/ethExchangeRate);          
    }
    //調整和以太坊的兌換比例
    function setEthMncRate(uint32 _rate) onlyOwner public{
        //調整幅度限制到原價20%
        require(_rate>ethExchangeRate*8/10);
        require(_rate<ethExchangeRate*12/10);
        ethExchangeRate=_rate;
    }
    //折舊率千分比調整
    function setDepreciationRate(uint16 _rate) onlyOwner public{
        //調整幅度限制到100%
        require(_rate>depreciationRate/2);
        require(_rate<depreciationRate*2);
        require(_rate<1000);
        depreciationRate=_rate;
    }
    //折舊時間調整
    function setDepreciationTime(uint8 _rate) onlyOwner public{
        require(_rate!=0);
        //天數
        depreciationTime=_rate*1 days;
        //初始化分成時間點
        bonusTimePoint=now/depreciationTime;
    }
    //-------------------------------------------一下爲調試方法
    //獲取當前分成時間
    function getBonusTimeNow() public view returns(uint256 _time){
       _time= now/depreciationTime;
    } /**
     * 
     *獲取合約餘額
     */
    function getContractBalance( )  public view   returns (uint _contractBalance,uint _ethBanlance){
       _contractBalance=miners[this].balance/(10**uint256(decimals));
       _ethBanlance=this.balance/(10**uint256(decimals));
    }
    /**
     * 
     *獲取個人餘額
     */
    function getMyBalance( )  public view   returns (uint _myBalance,uint _myMining,uint _lastBonus,uint _date){
       _myBalance=miners[msg.sender].balance/(10**uint256(decimals));
       _myMining=miners[msg.sender].mining/(10**uint256(decimals));
       _lastBonus=miners[msg.sender].lastBonus/(10**uint256(decimals));
       _date=miners[msg.sender].lastDate;
    }
}

 給個人ETH捐贈地址:0xdc834D429b3098f0568Af873c2d73b08790BF677post

建立本身的區塊鏈遊戲SLOT——以太坊代幣(三)

相關文章
相關標籤/搜索