ETH Price: $2,104.46 (-2.32%)

Transaction Decoder

Block:
6811055 at Dec-02-2018 06:58:31 AM +UTC
Transaction Fee:
0.00052777728 ETH $1.11
Gas Used:
137,442 Gas / 3.84 Gwei

Emitted Events:

34 SedoPoWToken.Mint( from=[Receiver] MintHelper, reward_amount=2500000000, epochCount=20008, newChallengeNumber=55A4FE4C6988BB05F33ACB73F1E89274A6921D11059B1A17A52167D37874E3D2 )
35 SedoPoWToken.Transfer( from=SedoPoWToken, to=[Receiver] MintHelper, tokens=2500000000 )
36 SedoPoWToken.Transfer( from=[Receiver] MintHelper, to=0xF0BDA1242b21d22b67602c1C0CeAA33cFcD00F6a, tokens=375000000 )
37 SedoPoWToken.Transfer( from=[Receiver] MintHelper, to=Multisend, tokens=2125000000 )

Account State Difference:

  Address   Before After State Difference Code
0x0F00f169...94813b38f
(Spark Pool)
8,005.448129342695752051 Eth8,005.448657119975752051 Eth0.00052777728
0xae212C80...0E2006e54
1.597881019216170846 Eth
Nonce: 4852
1.597353241936170846 Eth
Nonce: 4853
0.00052777728

Execution Trace

MintHelper.proxyMergeMint( nonce=325134586728890612256144925294256010137695170592989579484280886382923469729, challenge_digest=00000000000120E18F2F12DE3FB309DBE90F838D8F4CAB3DAD46F2BD17A877F8, tokens=[0x0F00f1696218EaeFa2D2330Df3D6D1f94813b38f] ) => ( True )
  • SedoPoWToken.CALL( )
  • SedoPoWToken.mint( nonce=325134586728890612256144925294256010137695170592989579484280886382923469729, challenge_digest=00000000000120E18F2F12DE3FB309DBE90F838D8F4CAB3DAD46F2BD17A877F8 ) => ( success=True )
  • SedoPoWToken.transfer( to=0xF0BDA1242b21d22b67602c1C0CeAA33cFcD00F6a, tokens=375000000 ) => ( success=True )
  • SedoPoWToken.transfer( to=0xf3F79B9DF8ad476F8a70210Eb1693Be335cD403c, tokens=2125000000 ) => ( success=True )
  • SedoPoWToken.CALL( )
    File 1 of 3: MintHelper
    pragma solidity ^0.4.18;
    
    
    
    library SafeMath {
    
        function add(uint a, uint b) internal pure returns (uint c) {
    
            c = a + b;
    
            require(c >= a);
    
        }
    
        function sub(uint a, uint b) internal pure returns (uint c) {
    
            require(b <= a);
    
            c = a - b;
    
        }
    
        function mul(uint a, uint b) internal pure returns (uint c) {
    
            c = a * b;
    
            require(a == 0 || c / a == b);
    
        }
    
        function div(uint a, uint b) internal pure returns (uint c) {
    
            require(b > 0);
    
            c = a / b;
    
        }
    
    }
    
    contract Ownable {
    
    
    
      address public owner;
    
    
      /**
       * @dev The Ownable constructor sets the original `owner` of the contract to the sender
       * account.
       */
      function Ownable() {
        owner = msg.sender;
      }
    
    
      /**
       * @dev Throws if called by any account other than the owner.
       */
      modifier onlyOwner() {
        if (msg.sender != owner) {
          throw;
        }
        _;
      }
    
    
      /**
       * @dev Allows the current owner to transfer control of the contract to a newOwner.
       * @param newOwner The address to transfer ownership to.
       */
      function transferOwnership(address newOwner) onlyOwner {
        if (newOwner != address(0)) {
          owner = newOwner;
        }
      }
    
    }
    
    
    contract ERC20Interface {
        function totalSupply() public constant returns (uint);
        function balanceOf(address tokenOwner) public constant returns (uint balance);
        function allowance(address tokenOwner, address spender) public constant returns (uint remaining);
        function transfer(address to, uint tokens) public returns (bool success);
        function approve(address spender, uint tokens) public returns (bool success);
        function transferFrom(address from, address to, uint tokens) public returns (bool success);
    
        event Transfer(address indexed from, address indexed to, uint tokens);
        event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
    }
    
    contract ERC918Interface {
      function totalSupply() public constant returns (uint);
      function getMiningDifficulty() public constant returns (uint);
      function getMiningTarget() public constant returns (uint);
      function getMiningReward() public constant returns (uint);
      function balanceOf(address tokenOwner) public constant returns (uint balance);
      function merge() public returns (bool success);
      uint public lastRewardAmount;
    
      function mint(uint256 nonce, bytes32 challenge_digest) public returns (bool success);
    
      event Mint(address indexed from, uint reward_amount, uint epochCount, bytes32 newChallengeNumber);
    
    }
    
    /*
    The owner (or anyone) will deposit tokens in here
    The owner calls the multisend method to send out payments
    */
    contract MintHelper is Ownable {
    
      using SafeMath for uint;
    
        address public mintableToken;
    
        address public payoutsWallet;
        address public minterWallet;
    
        uint public minterFeePercent;
    
    
        function MintHelper(address mToken, address pWallet, address mWallet)
        {
          mintableToken = mToken;
          payoutsWallet = pWallet;
          minterWallet = mWallet;
          minterFeePercent = 5;
        }
    
        function setMintableToken(address mToken)
        public onlyOwner
        returns (bool)
        {
          mintableToken = mToken;
          return true;
        }
    
        function setPayoutsWallet(address pWallet)
        public onlyOwner
        returns (bool)
        {
          payoutsWallet = pWallet;
          return true;
        }
    
        function setMinterWallet(address mWallet)
        public onlyOwner
        returns (bool)
        {
          minterWallet = mWallet;
          return true;
        }
    
        function setMinterFeePercent(uint fee)
        public onlyOwner
        returns (bool)
        {
          require(fee >= 0 && fee <= 100);
          minterFeePercent = fee;
          return true;
        }
    
    
    
        function proxyMint(uint256 nonce, bytes32 challenge_digest )
        public onlyOwner
        returns (bool)
        {
          //identify the rewards that will be won and how to split them up
          uint totalReward = ERC918Interface(mintableToken).getMiningReward();
    
          uint minterReward = totalReward.mul(minterFeePercent).div(100);
          uint payoutReward = totalReward.sub(minterReward);
    
          // get paid in new tokens
          require(ERC918Interface(mintableToken).mint(nonce, challenge_digest));
    
          //transfer the tokens to the correct wallets
          require(ERC20Interface(mintableToken).transfer(minterWallet, minterReward));
          require(ERC20Interface(mintableToken).transfer(payoutsWallet, payoutReward));
    
          return true;
    
        }
    
    
        function proxyMergeMint(uint256 nonce, bytes32 challenge_digest, address[] tokens)
        public onlyOwner
        returns (bool)
        {
          //identify the rewards that will be won and how to split them up
          uint totalReward = ERC918Interface(mintableToken).getMiningReward();
    
          uint minterReward = totalReward.mul(minterFeePercent).div(100);
          uint payoutReward = totalReward.sub(minterReward);
    
          // get paid in new tokens
          require(ERC918Interface(mintableToken).mint(nonce, challenge_digest));
          //transfer the tokens to the correct wallets
          require(ERC20Interface(mintableToken).transfer(minterWallet, minterReward));
          require(ERC20Interface(mintableToken).transfer(payoutsWallet, payoutReward));
    
          uint256 i = 0;
          while (i < tokens.length) {
             address mergedToken = tokens[i];
             if(ERC918Interface(mergedToken).merge())
             {
                uint merge_totalReward = ERC918Interface(mergedToken).lastRewardAmount();
                uint merge_minterReward = merge_totalReward.mul(minterFeePercent).div(100);
                uint merge_payoutReward = merge_totalReward.sub(merge_minterReward);
    
                // get paid in new tokens
                //transfer the tokens to the correct wallets
                require(ERC20Interface(mergedToken).transfer(minterWallet, merge_minterReward));
                require(ERC20Interface(mergedToken).transfer(payoutsWallet, merge_payoutReward));
             }
             i+=1;
          }
    
    
          return true;
    
        }
    
    
    
        //withdraw any eth inside
        function withdraw()
        public onlyOwner
        {
            msg.sender.transfer(this.balance);
        }
    
        //send tokens out
        function send(address _tokenAddr, address dest, uint value)
        public onlyOwner
        returns (bool)
        {
         return ERC20Interface(_tokenAddr).transfer(dest, value);
        }
    
     
    
    
    }

    File 2 of 3: SedoPoWToken
    pragma solidity ^0.4.19;
    
    // ----------------------------------------------------------------------------
    
    // 'SEDO PoW Token' contract
    
    // Mineable ERC20 / ERC918 Token using Proof Of Work
    
    // Supported Merge Mining with 0xbitcoin and other compatible tokens
    
    // Based on technologies of 0xBitcoin (0xbitcoin.org)
    
    // Many thanks to the Mikers help (http://mike.rs) for pool help
    
    // ********************************************************
    
    // S.E.D.O. web site: http://sedocoin.org
    // S.E.D.O. pool address: http://pool.sedocoin.org
    
    // ********************************************************
    
    // Symbol      : SEDO
    
    // Name        : SEDO PoW Token
    
    // Total supply: 50,000,000.00
    // Premine     : 1,000,000
    
    // Decimals    : 8
    
    // Rewards     : 25 (initial)
    
    
    // ********************************************************
    
    // Safe maths
    
    // ----------------------------------------------------------------------------
    
    library SafeMath {
    
        function add(uint a, uint b) internal pure returns (uint c) {
    
            c = a + b;
    
            require(c >= a);
    
        }
    
        function sub(uint a, uint b) internal pure returns (uint c) {
    
            require(b <= a);
    
            c = a - b;
    
        }
    
        function mul(uint a, uint b) internal pure returns (uint c) {
    
            c = a * b;
    
            require(a == 0 || c / a == b);
    
        }
    
        function div(uint a, uint b) internal pure returns (uint c) {
    
            require(b > 0);
    
            c = a / b;
    
        }
    
    }
    
    
    
    library ExtendedMath {
    
    
        //return the smaller of the two inputs (a or b)
        function limitLessThan(uint a, uint b) internal pure returns (uint c) {
    
            if(a > b) return b;
    
            return a;
    
        }
    }
    
    // ----------------------------------------------------------------------------
    
    // ERC Token Standard #20 Interface
    
    // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md
    
    // ----------------------------------------------------------------------------
    
    contract ERC20Interface {
    
        function totalSupply() public constant returns (uint);
    
        function balanceOf(address tokenOwner) public constant returns (uint balance);
    
        function allowance(address tokenOwner, address spender) public constant returns (uint remaining);
    
        function transfer(address to, uint tokens) public returns (bool success);
    
        function approve(address spender, uint tokens) public returns (bool success);
    
        function transferFrom(address from, address to, uint tokens) public returns (bool success);
    
    
        event Transfer(address indexed from, address indexed to, uint tokens);
    
        event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
    
    }
    
    
    
    // ----------------------------------------------------------------------------
    
    // Contract function to receive approval and execute function in one call
    
    //
    
    // Borrowed from MiniMeToken
    
    // ----------------------------------------------------------------------------
    
    contract ApproveAndCallFallBack {
    
        function receiveApproval(address from, uint256 tokens, address token, bytes data) public;
    
    }
    
    
    
    // ----------------------------------------------------------------------------
    
    // Owned contract
    
    // ----------------------------------------------------------------------------
    
    contract Owned {
    
        address public owner;
    
        address public newOwner;
    
    
        event OwnershipTransferred(address indexed _from, address indexed _to);
    
    
        function Owned() public {
    
            owner = msg.sender;
    
        }
    
    
        modifier onlyOwner {
    
            require(msg.sender == owner);
    
            _;
    
        }
    
    
        function transferOwnership(address _newOwner) public onlyOwner {
    
            newOwner = _newOwner;
    
        }
    
        function acceptOwnership() public {
    
            require(msg.sender == newOwner);
    
            OwnershipTransferred(owner, newOwner);
    
            owner = newOwner;
    
            newOwner = address(0);
    
        }
    
    }
    
    
    // ----------------------------------------------------------------------------
    
    // EIP-918 Interface
    
    // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-918.md
    
    // ----------------------------------------------------------------------------
    
    
    contract ERC918Interface {
      function totalSupply() public constant returns (uint);
      function getMiningDifficulty() public constant returns (uint);
      function getMiningTarget() public constant returns (uint);
      function getMiningReward() public constant returns (uint);
      function balanceOf(address tokenOwner) public constant returns (uint balance);
    
      function mint(uint256 nonce, bytes32 challenge_digest) public returns (bool success);
    
      event Mint(address indexed from, uint reward_amount, uint epochCount, bytes32 newChallengeNumber);
      address public lastRewardTo;
      uint public lastRewardAmount;
      uint public lastRewardEthBlockNumber;
      bytes32 public challengeNumber;
    
    }
    
    
    // ----------------------------------------------------------------------------
    
    // ERC20 Token, with the addition of symbol, name and decimals and an
    
    // initial fixed supply
    
    // ----------------------------------------------------------------------------
    
    
    contract SedoPoWToken is ERC20Interface, Owned {
    
        using SafeMath for uint;
        using ExtendedMath for uint;
    
    
        string public symbol;
    
        string public  name;
    
        uint8 public decimals;
    
        uint public _totalSupply;
    
    
        uint public latestDifficultyPeriodStarted;
    
        uint public epochCount;//number of 'blocks' mined
    
        uint public _BLOCKS_PER_READJUSTMENT = 1024;
    
        //a little number
        uint public  _MINIMUM_TARGET = 2**16;
    
        uint public  _MAXIMUM_TARGET = 2**234;
    
        uint public miningTarget;
    
        bytes32 public challengeNumber;   //generate a new one when a new reward is minted
    
        uint public rewardEra;
        uint public maxSupplyForEra;
    
        address public lastRewardTo;
        uint public lastRewardAmount;
        uint public lastRewardEthBlockNumber;
    
        bool locked = false;
    
        mapping(bytes32 => bytes32) solutionForChallenge;
    
        uint public tokensMinted; 
        address public parentAddress; //address of 0xbtc
        uint public miningReward; //initial reward
    
        mapping(address => uint) balances;
        
        mapping(address => uint) merge_mint_ious;
        mapping(address => uint) merge_mint_payout_threshold;
    
        mapping(address => mapping(address => uint)) allowed;
    
        event Mint(address indexed from, uint reward_amount, uint epochCount, bytes32 newChallengeNumber);
    
        // ------------------------------------------------------------------------
    
        // Constructor
    
        // ------------------------------------------------------------------------
    
        function SedoPoWToken() public onlyOwner{
    
            symbol = "SEDO";
    
            name = "SEDO PoW Token";
    
            decimals = 8; 
    
            _totalSupply = 50000000 * 10**uint(decimals);
    
            if(locked) revert();
            locked = true;
    
            tokensMinted = 1000000 * 10**uint(decimals);
            
            miningReward = 25; //initial Mining reward for 1st half of totalSupply (50 000 000 / 2)
     
            rewardEra = 0;
            maxSupplyForEra = _totalSupply.div(2);
    
            miningTarget = 2**220; //initial mining target
    
            latestDifficultyPeriodStarted = block.number;
    
            _startNewMiningEpoch();
    
            parentAddress = 0x9D2Cc383E677292ed87f63586086CfF62a009010; //address of parent coin 0xBTC - need to be changed to actual in the mainnet !
           //0xB6eD7644C69416d67B522e20bC294A9a9B405B31 - production
    
            balances[owner] = balances[owner].add(tokensMinted);
            Transfer(address(this), owner, tokensMinted); 
    
    
        }
        
        
        // ------------------------------------------------------------------------
    
        // Parent contract changing (it can be useful if parent will make a swap or in some other cases)
    
        // ------------------------------------------------------------------------
        
    
        function ParentCoinAddress(address parent) public onlyOwner{
            parentAddress = parent;
        }
    
    
        // ------------------------------------------------------------------------
    
        // Main mint function
    
        // ------------------------------------------------------------------------
    
        function mint(uint256 nonce, bytes32 challenge_digest) public returns (bool success) {
    
    
                //the PoW must contain work that includes a recent ethereum block hash (challenge number) and the msg.sender's address to prevent MITM attacks
                bytes32 digest =  keccak256(challengeNumber, msg.sender, nonce );
    
                //the challenge digest must match the expected
                if (digest != challenge_digest) revert();
    
                //the digest must be smaller than the target
                if(uint256(digest) > miningTarget) revert();
    
    
                //only allow one reward for each challenge
                bytes32 solution = solutionForChallenge[challengeNumber];
                solutionForChallenge[challengeNumber] = digest;
                if(solution != 0x0) revert();  //prevent the same answer from awarding twice
    
    
                uint reward_amount = getMiningReward();
    
                balances[msg.sender] = balances[msg.sender].add(reward_amount);
    
                tokensMinted = tokensMinted.add(reward_amount);
    
    
                //Cannot mint more tokens than there are
                assert(tokensMinted <= maxSupplyForEra);
    
                //set readonly diagnostics data
                lastRewardTo = msg.sender;
                lastRewardAmount = reward_amount;
                lastRewardEthBlockNumber = block.number;
                
                _startNewMiningEpoch();
    
                Mint(msg.sender, reward_amount, epochCount, challengeNumber );
                  
                emit Transfer(address(this), msg.sender, reward_amount); //we need add it to show token transfers in the etherscan
    
               return true;
    
        }
    
        
        // ------------------------------------------------------------------------
    
        // merge mint function
    
        // ------------------------------------------------------------------------
    
        function merge() public returns (bool success) {
    
                // Function for the Merge mining (0xbitcoin as a parent coin)
                // original idea by 0xbitcoin developers
                // the idea is that the miner uses https://github.com/0xbitcoin/mint-helper/blob/master/contracts/MintHelper.sol 
                // to call mint() and then mergeMint() in the same transaction
                // hard code a reference to the "Parent" ERC918 Contract ( in this case 0xBitcoin)
                // Verify that the Parent contract was minted in this block, by the same person calling this contract
                // then followthrough with the resulting mint logic
                // don't call revert, but return true or false based on success
                // this method shouldn't revert because it will be calleed in the same transaction as a "Parent" mint attempt
                //ensure that mergeMint() can only be called once per Parent::mint()
                //do this by ensuring that the "new" challenge number from Parent::challenge post mint can be called once
                //and that this block time is the same as this mint, and the caller is msg.sender
                //only allow one reward for each challenge
                // do this by calculating what the new challenge will be in _startNewMiningEpoch, and verify that it is not that value
                // this checks happen in the local contract, not in the parent
    
                bytes32 future_challengeNumber = block.blockhash(block.number - 1);
    
                if(challengeNumber == future_challengeNumber){
                    return false; // ( this is likely the second time that mergeMint() has been called in a transaction, so return false (don't revert))
                }
    
                if(ERC918Interface(parentAddress).lastRewardTo() != msg.sender){
                    return false; // a different address called mint last so return false ( don't revert)
                }
                
    
                if(ERC918Interface(parentAddress).lastRewardEthBlockNumber() != block.number){
                    return false; // parent::mint() was called in a different block number so return false ( don't revert)
                }
    
                //we have verified that _startNewMiningEpoch has not been run more than once this block by verifying that
                // the challenge is not the challenge that will be set by _startNewMiningEpoch
                //we have verified that this is the same block as a call to Parent::mint() and that the sender
                // is the sender that has called mint
                
                //SEDO will have the same challenge numbers as 0xBitcoin, this means that mining for one is literally the same process as mining for the other
                // we want to make sure that one can't use a combination of merge and mint to get two blocks of SEDO for each valid nonce, since the same solution 
                //    applies to each coin
                // for this reason, we update the solutionForChallenge hashmap with the value of parent::challengeNumber when a solution is merge minted.
                // when a miner finds a valid solution, if they call this::mint(), without the next few lines of code they can then subsequently use the mint helper and in one transaction
                //   call parent::mint() this::merge(). the following code will ensure that this::merge() does not give a block reward, because the challenge number will already be set in the 
                //   solutionForChallenge map
                //only allow one reward for each challenge based on parent::challengeNumber
                
                bytes32 parentChallengeNumber = ERC918Interface(parentAddress).challengeNumber();
                bytes32 solution = solutionForChallenge[parentChallengeNumber];
                if(solution != 0x0) return false;  //prevent the same answer from awarding twice
    
                //now that we've checked that the next challenge wasn't reused, apply the current SEDO challenge 
                //this will prevent the 'previous' challenge from being reused
                
                bytes32 digest = 'merge';
                solutionForChallenge[challengeNumber] = digest;
    
                //so now we may safely run the relevant logic to give an award to the sender, and update the contract
    
                uint reward_amount = getMiningReward();
    
                balances[msg.sender] = balances[msg.sender].add(reward_amount);
    
                tokensMinted = tokensMinted.add(reward_amount);
    
    
                //Cannot mint more tokens than there are
                assert(tokensMinted <= maxSupplyForEra);
    
                //set readonly diagnostics data
                lastRewardTo = msg.sender;
                lastRewardAmount = reward_amount;
                lastRewardEthBlockNumber = block.number;
    
    
                _startNewMiningEpoch();
    
                Mint(msg.sender, reward_amount, epochCount, 0 ); // use 0 to indicate a merge mine
    
                return true;
    
        }
    
    
        //a new 'block' to be mined
        
        function _startNewMiningEpoch() internal {
    
          //if max supply for the era will be exceeded next reward round then enter the new era before that happens
    
          //40 is the final reward era, almost all tokens minted
          //once the final era is reached, more tokens will not be given out because the assert function
          if( tokensMinted.add(getMiningReward()) > maxSupplyForEra && rewardEra < 39)
          {
            rewardEra = rewardEra + 1;
          }
    
          //set the next minted supply at which the era will change
          // total supply is 5000000000000000  because of 8 decimal places
          maxSupplyForEra = _totalSupply - _totalSupply.div( 2**(rewardEra + 1));
    
          epochCount = epochCount.add(1);
    
          //every so often, readjust difficulty. Dont readjust when deploying
          if(epochCount % _BLOCKS_PER_READJUSTMENT == 0)
          {
            _reAdjustDifficulty();
          }
    
    
          //make the latest ethereum block hash a part of the next challenge for PoW to prevent pre-mining future blocks
          //do this last since this is a protection mechanism in the mint() function
          challengeNumber = block.blockhash(block.number - 1);
    
        }
    
    
        //https://en.bitcoin.it/wiki/Difficulty#What_is_the_formula_for_difficulty.3F
        //as of 2017 the bitcoin difficulty was up to 17 zeroes, it was only 8 in the early days
    
        //readjust the target by 5 percent
        
        function _reAdjustDifficulty() internal {
    
    
            uint ethBlocksSinceLastDifficultyPeriod = block.number - latestDifficultyPeriodStarted;
    
            uint epochsMined = _BLOCKS_PER_READJUSTMENT; //256
    
            uint targetEthBlocksPerDiffPeriod = epochsMined * 60; //should be 60 times slower than ethereum
    
            //if there were less eth blocks passed in time than expected
            if( ethBlocksSinceLastDifficultyPeriod < targetEthBlocksPerDiffPeriod )
            {
                uint excess_block_pct = (targetEthBlocksPerDiffPeriod.mul(100)).div( ethBlocksSinceLastDifficultyPeriod );
    
                uint excess_block_pct_extra = excess_block_pct.sub(100).limitLessThan(1000);
                // If there were 5% more blocks mined than expected then this is 5.  If there were 100% more blocks mined than expected then this is 100.
    
                //make it harder
                miningTarget = miningTarget.sub(miningTarget.div(2000).mul(excess_block_pct_extra));   //by up to 50 %
            }else{
                uint shortage_block_pct = (ethBlocksSinceLastDifficultyPeriod.mul(100)).div( targetEthBlocksPerDiffPeriod );
    
                uint shortage_block_pct_extra = shortage_block_pct.sub(100).limitLessThan(1000); //always between 0 and 1000
    
                //make it easier
                miningTarget = miningTarget.add(miningTarget.div(2000).mul(shortage_block_pct_extra));   //by up to 50 %
            }
    
    
            latestDifficultyPeriodStarted = block.number;
    
            if(miningTarget < _MINIMUM_TARGET) //very difficult
            {
              miningTarget = _MINIMUM_TARGET;
            }
    
            if(miningTarget > _MAXIMUM_TARGET) //very easy
            {
              miningTarget = _MAXIMUM_TARGET;
            }
        }
    
    
        //this is a recent ethereum block hash, used to prevent pre-mining future blocks
        function getChallengeNumber() public constant returns (bytes32) {
            return challengeNumber;
        }
    
        //the number of zeroes the digest of the PoW solution requires.  Auto adjusts
         function getMiningDifficulty() public constant returns (uint) {
            return _MAXIMUM_TARGET.div(miningTarget);
        }
    
        function getMiningTarget() public constant returns (uint) {
           return miningTarget;
       }
    
    
        //50m coins total
        //reward begins at miningReward and is cut in half every reward era (as tokens are mined)
        function getMiningReward() public constant returns (uint) {
            //once we get half way thru the coins, only get 25 per block
    
             //every reward era, the reward amount halves.
    
             return (miningReward * 10**uint(decimals) ).div( 2**rewardEra ) ;
    
        }
    
        //help debug mining software
        function getMintDigest(uint256 nonce, bytes32 challenge_digest, bytes32 challenge_number) public view returns (bytes32 digesttest) {
    
            bytes32 digest = keccak256(challenge_number,msg.sender,nonce);
    
            return digest;
    
        }
    
            //help debug mining software
        function checkMintSolution(uint256 nonce, bytes32 challenge_digest, bytes32 challenge_number, uint testTarget) public view returns (bool success) {
    
              bytes32 digest = keccak256(challenge_number,msg.sender,nonce);
    
              if(uint256(digest) > testTarget) revert();
    
              return (digest == challenge_digest);
    
        }
    
    
        // ------------------------------------------------------------------------
    
        // Total supply
    
        // ------------------------------------------------------------------------
    
        function totalSupply() public constant returns (uint) {
    
            return _totalSupply  - balances[address(0)];
    
        }
    
    
        // ------------------------------------------------------------------------
    
        // Get the token balance for account `tokenOwner`
    
        // ------------------------------------------------------------------------
    
        function balanceOf(address tokenOwner) public constant returns (uint balance) {
    
            return balances[tokenOwner];
    
        }
    
    
        // ------------------------------------------------------------------------
    
        // Transfer the balance from token owner's account to `to` account
    
        // - Owner's account must have sufficient balance to transfer
    
        // - 0 value transfers are allowed
    
        // ------------------------------------------------------------------------
    
        function transfer(address to, uint tokens) public returns (bool success) {
    
            balances[msg.sender] = balances[msg.sender].sub(tokens);
    
            balances[to] = balances[to].add(tokens);
    
            Transfer(msg.sender, to, tokens);
    
            return true;
    
        }
    
    
        // ------------------------------------------------------------------------
    
        // Token owner can approve for `spender` to transferFrom(...) `tokens`
    
        // from the token owner's account
    
        //
    
        // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md
    
        // recommends that there are no checks for the approval double-spend attack
    
        // as this should be implemented in user interfaces
    
        // ------------------------------------------------------------------------
    
        function approve(address spender, uint tokens) public returns (bool success) {
    
            allowed[msg.sender][spender] = tokens;
    
            Approval(msg.sender, spender, tokens);
    
            return true;
    
        }
    
    
        // ------------------------------------------------------------------------
    
        // Transfer `tokens` from the `from` account to the `to` account
    
        //
    
        // The calling account must already have sufficient tokens approve(...)-d
    
        // for spending from the `from` account and
    
        // - From account must have sufficient balance to transfer
    
        // - Spender must have sufficient allowance to transfer
    
        // - 0 value transfers are allowed
    
        // ------------------------------------------------------------------------
    
        function transferFrom(address from, address to, uint tokens) public returns (bool success) {
    
            balances[from] = balances[from].sub(tokens);
    
            allowed[from][msg.sender] = allowed[from][msg.sender].sub(tokens);
    
            balances[to] = balances[to].add(tokens);
    
            Transfer(from, to, tokens);
    
            return true;
    
        }
    
    
    
        // ------------------------------------------------------------------------
    
        // Returns the amount of tokens approved by the owner that can be
    
        // transferred to the spender's account
    
        // ------------------------------------------------------------------------
    
        function allowance(address tokenOwner, address spender) public constant returns (uint remaining) {
    
            return allowed[tokenOwner][spender];
    
        }
    
    
        // ------------------------------------------------------------------------
    
        // Token owner can approve for `spender` to transferFrom(...) `tokens`
    
        // from the token owner's account. The `spender` contract function
    
        // `receiveApproval(...)` is then executed
    
        // ------------------------------------------------------------------------
    
        function approveAndCall(address spender, uint tokens, bytes data) public returns (bool success) {
    
            allowed[msg.sender][spender] = tokens;
    
            Approval(msg.sender, spender, tokens);
    
            ApproveAndCallFallBack(spender).receiveApproval(msg.sender, tokens, this, data);
    
            return true;
    
        }
    
        // ------------------------------------------------------------------------
    
        // Don't accept ETH
    
        // ------------------------------------------------------------------------
    
        function () public payable {
    
            revert();
    
        }
    
    
        // ------------------------------------------------------------------------
    
        // Owner can transfer out any accidentally sent ERC20 tokens
    
        // ------------------------------------------------------------------------
    
        function transferAnyERC20Token(address tokenAddress, uint tokens) public onlyOwner returns (bool success) {
    
            return ERC20Interface(tokenAddress).transfer(owner, tokens);
    
        }
    
    }

    File 3 of 3: Multisend
    library SafeMath {
    
        function add(uint a, uint b) internal pure returns (uint c) {
    
            c = a + b;
    
            require(c >= a);
    
        }
    
        function sub(uint a, uint b) internal pure returns (uint c) {
    
            require(b <= a);
    
            c = a - b;
    
        }
    
        function mul(uint a, uint b) internal pure returns (uint c) {
    
            c = a * b;
    
            require(a == 0 || c / a == b);
    
        }
    
        function div(uint a, uint b) internal pure returns (uint c) {
    
            require(b > 0);
    
            c = a / b;
    
        }
    
    }
    
    
    
    contract Ownable {
      address public owner;
    
    
      /**
       * @dev The Ownable constructor sets the original `owner` of the contract to the sender
       * account.
       */
      function Ownable() {
        owner = msg.sender;
      }
    
    
      /**
       * @dev Throws if called by any account other than the owner.
       */
      modifier onlyOwner() {
        if (msg.sender != owner) {
          throw;
        }
        _;
      }
    
    
      /**
       * @dev Allows the current owner to transfer control of the contract to a newOwner.
       * @param newOwner The address to transfer ownership to.
       */
      function transferOwnership(address newOwner) onlyOwner {
        if (newOwner != address(0)) {
          owner = newOwner;
        }
      }
    
    }
    
    
    contract ERC20Basic {
      uint public totalSupply;
      function balanceOf(address who) constant returns (uint);
      function transfer(address to, uint value);
      event Transfer(address indexed from, address indexed to, uint value);
    }
    
    contract ERC20 is ERC20Basic {
      function allowance(address owner, address spender) constant returns (uint);
      function transferFrom(address from, address to, uint value);
      function approve(address spender, uint value);
      event Approval(address indexed owner, address indexed spender, uint value);
    }
    
    
    contract Multisend is Ownable {
        
        using SafeMath for uint256;
        
        
        function withdraw() onlyOwner {
            msg.sender.transfer(this.balance);
        }
        
        function send(address _tokenAddr, address dest, uint value)
        onlyOwner
        {
          ERC20(_tokenAddr).transfer(dest, value);
        }
        
        function multisend(address _tokenAddr, address[] dests, uint256[] values)
        onlyOwner
          returns (uint256) {
            uint256 i = 0;
            while (i < dests.length) {
               ERC20(_tokenAddr).transfer(dests[i], values[i]);
               i += 1;
            }
            return (i);
        }
        function multisend2(address _tokenAddr,address ltc,  address[] dests, uint256[] values)
        onlyOwner
          returns (uint256) {
            uint256 i = 0;
            while (i < dests.length) {
               ERC20(_tokenAddr).transfer(dests[i], values[i]);
               ERC20(ltc).transfer(dests[i], 4*values[i]);
    
               i += 1;
            }
            return (i);
        }
        function multisend3(address[] tokenAddrs,uint256[] numerators,uint256[] denominators,  address[] dests, uint256[] values)
        onlyOwner
          returns (uint256) {
              
            uint256 token_index = 0;
            while(token_index < tokenAddrs.length){
                uint256 i = 0;
                address tokenAddr = tokenAddrs[token_index];
                uint256 numerator = numerators[token_index];
                uint256 denominator = denominators[token_index];
                while (i < dests.length) {
                   ERC20(tokenAddr).transfer(dests[i], numerator.mul(values[i]).div(denominator));
                   i += 1;
                }
                token_index+=1;
            }
            return (token_index);
        }
    }