• 创建自己的加密货币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——以太坊代币(三)

  • 相关阅读:
    Wiin10 深色模式 暗色 省电 经济 护眼dark mode energy saving ecol
    云主机终端现实中文
    systemctl enable与systemctl start的区别
    centos技巧
    用国内的vps登录亚马逊的ec2
    小米 redmi note 8 打开开发者选项
    javascript数组、对象和Null的typeof同为object,区分解决办法
    组件中是否可以判断slot是否有内容?
    xlsx-style 行高设置
    修改xlsx-style 源码 解决报错
  • 原文地址:https://www.cnblogs.com/lixiaoran/p/9132576.html
Copyright © 2020-2023  润新知