創建自己的加密貨幣MNC——以太坊代幣(二)


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

https://github.com/lxr1907/MNC

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

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

3.衰減,由於礦機有折舊衰減損壞的概率,token會隨着持有時間而衰減。

代碼如下

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捐贈地址:0xdc834D429b3098f0568Af873c2d73b08790BF677

創建自己的區塊鏈游戲SLOT——以太坊代幣(三)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM