建立一個基於以太坊平臺的分成幣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