├── contracts ├── 0xdogeExample.sol ├── ExtendedMath.sol ├── 0xdogeExample2.sol ├── SafeMath.sol ├── Owned.sol ├── SimpleERC918.sol ├── EIP918Interface.sol ├── EIP20Interface.sol ├── AbstractERC918.sol ├── 0xBitcoinBase.sol └── EIP918_Example.sol ├── truffle.js ├── 0xBitcoin_Mint.md └── README.md /contracts/0xdogeExample.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.18; 2 | import "./0xBitcoinBase.sol"; 3 | /* Three liner to create a 0xb based mineable token */ 4 | contract _0xdoge is _0xBitcoinBase('0xDoge', '0xDoge Mineable Token', 113000000000, 12, 200, 512) { } -------------------------------------------------------------------------------- /contracts/ExtendedMath.sol: -------------------------------------------------------------------------------- 1 | 2 | pragma solidity ^0.4.18; 3 | 4 | library ExtendedMath { 5 | 6 | 7 | //return the smaller of the two inputs (a or b) 8 | function limitLessThan(uint a, uint b) internal pure returns (uint c) { 9 | 10 | if(a > b) return b; 11 | 12 | return a; 13 | 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /truffle.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | networks: { 3 | development: { 4 | host: "localhost", 5 | port: 8545, 6 | network_id: "*" // Match any network id 7 | }, 8 | ropsten: { 9 | network_id: 3, 10 | host: "localhost", 11 | port: 8545, 12 | gas: 2900000 13 | 14 | } 15 | }, 16 | rpc: { 17 | host: 'localhost', 18 | post:8080 19 | } 20 | }; 21 | -------------------------------------------------------------------------------- /contracts/0xdogeExample2.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.18; 2 | 3 | import "./0xBitcoinBase.sol"; 4 | /* Create a 0xb based mineable token */ 5 | contract _0xdoge is _0xBitcoinBase('0xDoge', '0xDoge Mineable Token', 113000000000, 12, 200, 512) { 6 | 7 | /** 8 | * _hash function 9 | * 10 | * Override the default hash phase of the mine operation 11 | */ 12 | function _hash(uint256 nonce, bytes32 challenge_digest) internal returns (bytes32 digest) { 13 | /* call the base implementation of _hash if need be */ 14 | digest = super._hash(nonce, challenge_digest); 15 | /* doge specific nonce and challenge checks here */ 16 | 17 | } 18 | 19 | } -------------------------------------------------------------------------------- /contracts/SafeMath.sol: -------------------------------------------------------------------------------- 1 | 2 | pragma solidity ^0.4.18; 3 | 4 | library SafeMath { 5 | 6 | function add(uint a, uint b) internal pure returns (uint c) { 7 | 8 | c = a + b; 9 | 10 | require(c >= a); 11 | 12 | } 13 | 14 | function sub(uint a, uint b) internal pure returns (uint c) { 15 | 16 | require(b <= a); 17 | 18 | c = a - b; 19 | 20 | } 21 | 22 | function mul(uint a, uint b) internal pure returns (uint c) { 23 | 24 | c = a * b; 25 | 26 | require(a == 0 || c / a == b); 27 | 28 | } 29 | 30 | function div(uint a, uint b) internal pure returns (uint c) { 31 | 32 | require(b > 0); 33 | 34 | c = a / b; 35 | 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /contracts/Owned.sol: -------------------------------------------------------------------------------- 1 | 2 | pragma solidity ^0.4.18; 3 | 4 | // ---------------------------------------------------------------------------- 5 | 6 | // Owned contract 7 | 8 | // ---------------------------------------------------------------------------- 9 | 10 | contract Owned { 11 | 12 | address public owner; 13 | 14 | address public newOwner; 15 | 16 | 17 | event OwnershipTransferred(address indexed _from, address indexed _to); 18 | 19 | 20 | function Owned() public { 21 | 22 | owner = msg.sender; 23 | 24 | } 25 | 26 | 27 | modifier onlyOwner { 28 | 29 | require(msg.sender == owner); 30 | 31 | _; 32 | 33 | } 34 | 35 | 36 | function transferOwnership(address _newOwner) public onlyOwner { 37 | 38 | newOwner = _newOwner; 39 | 40 | } 41 | 42 | function acceptOwnership() public { 43 | 44 | require(msg.sender == newOwner); 45 | 46 | OwnershipTransferred(owner, newOwner); 47 | 48 | owner = newOwner; 49 | 50 | newOwner = address(0); 51 | 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /contracts/SimpleERC918.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.18; 2 | 3 | import "./AbstractERC918.sol"; 4 | 5 | /** 6 | * Simple ERC918 Implementation 7 | * Proof of Work Mineable Token 8 | * 9 | * This Abstract contract implements a minimal set of behaviors (hash, reward, epoch, and difficulty adjustment) 10 | * and state required to build a Proof of Work driven mineable token. 11 | * 12 | * https://github.com/ethereum/EIPs/pull/918 13 | * https://www.ethereum.org/token#proof-of-work 14 | */ 15 | contract SimpleERC918 is AbstractERC918 { 16 | 17 | uint public timeOfLastProof; // Variable to keep track of when rewards were given 18 | 19 | function SimpleERC918() public { 20 | // Difficulty starts reasonably low 21 | difficulty = 10**32; 22 | } 23 | 24 | function _hash(uint256 nonce, bytes32 challenge_digest) internal returns (bytes32 digest) { 25 | digest = bytes32(keccak256(nonce, challenge_digest)); // Generate a random hash based on input 26 | require(digest >= bytes32(difficulty)); // Check if it's under the difficulty 27 | } 28 | 29 | function _reward() internal returns (uint rewardAmount) { 30 | uint timeSinceLastProof = (now - timeOfLastProof); // Calculate time since last reward was given 31 | require(timeSinceLastProof >= 5 seconds); // Rewards cannot be given too quickly 32 | rewardAmount = timeSinceLastProof / 60 seconds; 33 | balances[msg.sender] += rewardAmount; // The reward to the winner grows by the minute 34 | } 35 | 36 | function _newEpoch(uint256 nonce) internal returns (uint) { 37 | timeOfLastProof = now; // Reset the counter 38 | challengeNumber = keccak256(nonce, challengeNumber, block.blockhash(block.number - 1)); // Save a hash that will be used as the next proof 39 | } 40 | 41 | function _adjustDifficulty() internal returns (uint) { 42 | uint timeSinceLastProof = (now - timeOfLastProof); // Calculate time since last reward was given 43 | difficulty = difficulty * 10 minutes / (timeSinceLastProof + 1); // Adjusts the difficulty 44 | } 45 | 46 | } -------------------------------------------------------------------------------- /contracts/EIP918Interface.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.18; 2 | 3 | interface EIP918Interface { 4 | 5 | /* 6 | * Externally facing mint function that is called by miners to validate challenge digests, calculate reward, 7 | * populate statistics, mutate epoch variables and adjust the solution difficulty as required. Once complete, 8 | * a Mint event is emitted before returning a success indicator. 9 | **/ 10 | function mint(uint256 nonce, bytes32 challenge_digest) public returns (bool success); 11 | 12 | /* 13 | * Optional 14 | * Externally facing merge function that is called by miners to validate challenge digests, calculate reward, 15 | * populate statistics, mutate epoch variables and adjust the solution difficulty as required. Additionally, the 16 | * merge function takes an array of target token addresses to be used in merged rewards. Once complete, 17 | * a Mint event is emitted before returning a success indicator. 18 | **/ 19 | function merge(uint256 nonce, bytes32 challenge_digest, address[] mineTokens) public returns (bool success); 20 | 21 | /* 22 | * Returns the challenge number 23 | **/ 24 | function getChallengeNumber() public constant returns (bytes32); 25 | 26 | /* 27 | * Returns the mining difficulty. The number of digits that the digest of the PoW solution requires which 28 | * typically auto adjusts during reward generation. 29 | **/ 30 | function getMiningDifficulty() public constant returns (uint); 31 | 32 | /* 33 | * Returns the mining target 34 | **/ 35 | function getMiningTarget() public constant returns (uint); 36 | 37 | /* 38 | * Return the current reward amount. Depending on the algorithm, typically rewards are divided every reward era 39 | * as tokens are mined to provide scarcity 40 | **/ 41 | function getMiningReward() public constant returns (uint); 42 | 43 | /* 44 | * Upon successful verification and reward the mint method dispatches a Mint Event indicating the reward address, 45 | * the reward amount, the epoch count and newest challenge number. 46 | **/ 47 | event Mint(address indexed from, uint reward_amount, uint epochCount, bytes32 newChallengeNumber); 48 | 49 | } 50 | -------------------------------------------------------------------------------- /0xBitcoin_Mint.md: -------------------------------------------------------------------------------- 1 | The most important method for EIP918 is mint() for the token distribution and it is incorporated as follows for a SHA3 algorithm: 2 | 3 | 4 | uint challengeNumber = block.blockhash(block.number - 1); 5 | uint miningTarget = 2**224; 6 | uint epochCount = 0; 7 | 8 | function mint(uint256 nonce, bytes32 challenge_digest) public returns (bool success) { 9 | 10 | bytes32 digest = keccak256(challengeNumber, msg.sender, nonce); 11 | 12 | //the challenge digest must match the expected 13 | if (digest != challenge_digest) revert(); 14 | 15 | //the digest must be smaller than the target 16 | if(uint256(digest) > miningTarget) revert(); 17 | 18 | //only allow one reward for each unique proof of work 19 | bytes32 solution = solutionForChallenge[challengeNumber]; 20 | solutionForChallenge[challengeNumber] = digest; 21 | if(solution != 0x0) revert(); 22 | 23 | //implement a custom method for number of tokens to reward for a mint 24 | uint rewardAmount = getMiningReward(); 25 | 26 | //use safe math to add tokens to the miners account 27 | balances[msg.sender] = balances[msg.sender].add(rewardAmount); 28 | 29 | //set the challenge number to a 'random' new value so future blocks cannot be premined 30 | challengeNumber = block.blockhash(block.number - 1); 31 | 32 | //A method can be added here which adjusts the mining target in order to adjust difficulty 33 | //_adjustMiningTarget() 34 | 35 | //track the number of mints that have occured 36 | epochCount = epochCount.add(1); 37 | 38 | //fire an event 39 | Mint(msg.sender, rewardAmount, epochCount, challengeNumber ); 40 | 41 | return true; 42 | 43 | } 44 | 45 | function getChallengeNumber() public constant returns (bytes32) { 46 | return challengeNumber; 47 | } 48 | 49 | function getMiningTarget() public constant returns (uint) { 50 | return miningTarget; 51 | } 52 | 53 | 54 | function getMiningReward() public constant returns (uint) { 55 | //Feel free to modify this integer 56 | return 50 * 10**uint(decimals); 57 | } 58 | -------------------------------------------------------------------------------- /contracts/EIP20Interface.sol: -------------------------------------------------------------------------------- 1 | // Abstract contract for the full ERC 20 Token standard 2 | // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md 3 | pragma solidity ^0.4.18; 4 | 5 | 6 | contract EIP20Interface { 7 | /* This is a slight change to the ERC20 base standard. 8 | function totalSupply() constant returns (uint256 supply); 9 | is replaced with: 10 | uint256 public totalSupply; 11 | This automatically creates a getter function for the totalSupply. 12 | This is moved to the base contract since public getter functions are not 13 | currently recognised as an implementation of the matching abstract 14 | function by the compiler. 15 | */ 16 | /// total amount of tokens 17 | uint256 public totalSupply; 18 | 19 | /// @param _owner The address from which the balance will be retrieved 20 | /// @return The balance 21 | function balanceOf(address _owner) public view returns (uint256 balance); 22 | 23 | /// @notice send `_value` token to `_to` from `msg.sender` 24 | /// @param _to The address of the recipient 25 | /// @param _value The amount of token to be transferred 26 | /// @return Whether the transfer was successful or not 27 | function transfer(address _to, uint256 _value) public returns (bool success); 28 | 29 | /// @notice send `_value` token to `_to` from `_from` on the condition it is approved by `_from` 30 | /// @param _from The address of the sender 31 | /// @param _to The address of the recipient 32 | /// @param _value The amount of token to be transferred 33 | /// @return Whether the transfer was successful or not 34 | function transferFrom(address _from, address _to, uint256 _value) public returns (bool success); 35 | 36 | /// @notice `msg.sender` approves `_spender` to spend `_value` tokens 37 | /// @param _spender The address of the account able to transfer the tokens 38 | /// @param _value The amount of tokens to be approved for transfer 39 | /// @return Whether the approval was successful or not 40 | function approve(address _spender, uint256 _value) public returns (bool success); 41 | 42 | /// @param _owner The address of the account owning tokens 43 | /// @param _spender The address of the account able to transfer the tokens 44 | /// @return Amount of remaining tokens allowed to spent 45 | function allowance(address _owner, address _spender) public view returns (uint256 remaining); 46 | 47 | // solhint-disable-next-line no-simple-event-func-name 48 | event Transfer(address indexed _from, address indexed _to, uint256 _value); 49 | event Approval(address indexed _owner, address indexed _spender, uint256 _value); 50 | } 51 | -------------------------------------------------------------------------------- /contracts/AbstractERC918.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.18; 2 | 3 | import "./EIP918Interface.sol"; 4 | 5 | /** 6 | * ERC Draft Token Standard #918 Interface 7 | * Proof of Work Mineable Token 8 | * 9 | * This Abstract contract describes a minimal set of behaviors (hash, reward, epoch, and difficulty adjustment) 10 | * and state required to build a Proof of Work driven mineable token. 11 | * 12 | * https://github.com/ethereum/EIPs/pull/918 13 | */ 14 | contract AbstractERC918 is EIP918Interface { 15 | 16 | // generate a new challenge number after a new reward is minted 17 | bytes32 public challengeNumber; 18 | 19 | // the current mining difficulty 20 | uint public difficulty; 21 | 22 | // cumulative counter of the total minted tokens 23 | uint public tokensMinted; 24 | 25 | // track read only minting statistics 26 | struct Statistics { 27 | address lastRewardTo; 28 | uint lastRewardAmount; 29 | uint lastRewardEthBlockNumber; 30 | uint lastRewardTimestamp; 31 | } 32 | 33 | Statistics public statistics; 34 | 35 | /* 36 | * Externally facing mint function that is called by miners to validate challenge digests, calculate reward, 37 | * populate statistics, mutate epoch variables and adjust the solution difficulty as required. Once complete, 38 | * a Mint event is emitted before returning a success indicator. 39 | **/ 40 | function mint(uint256 nonce, bytes32 challenge_digest) public returns (bool success) { 41 | // perform the hash function validation 42 | _hash(nonce, challenge_digest); 43 | 44 | // calculate the current reward 45 | uint rewardAmount = _reward(); 46 | 47 | // increment the minted tokens amount 48 | tokensMinted += rewardAmount; 49 | 50 | uint epochCount = _newEpoch(nonce); 51 | 52 | _adjustDifficulty(); 53 | 54 | //populate read only diagnostics data 55 | statistics = Statistics(msg.sender, rewardAmount, block.number, now); 56 | 57 | // send Mint event indicating a successful implementation 58 | Mint(msg.sender, rewardAmount, epochCount, challengeNumber); 59 | 60 | return true; 61 | } 62 | 63 | /* 64 | * Internal interface function _hash. Overide in implementation to define hashing algorithm and 65 | * validation 66 | **/ 67 | function _hash(uint256 nonce, bytes32 challenge_digest) internal returns (bytes32 digest); 68 | 69 | /* 70 | * Internal interface function _reward. Overide in implementation to calculate and return reward 71 | * amount 72 | **/ 73 | function _reward() internal returns (uint); 74 | 75 | /* 76 | * Internal interface function _newEpoch. Overide in implementation to define a cutpoint for mutating 77 | * mining variables in preparation for the next epoch 78 | **/ 79 | function _newEpoch(uint256 nonce) internal returns (uint); 80 | 81 | /* 82 | * Internal interface function _adjustDifficulty. Overide in implementation to adjust the difficulty 83 | * of the mining as required 84 | **/ 85 | function _adjustDifficulty() internal returns (uint); 86 | 87 | } 88 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | --- 2 | eip: 3 | title: Mineable Token Standard 4 | author: Jay Logelin, Infernal_toast, Michael Seiler 5 | discussions-to: jlogelin@fas.harvard.edu, admin@0xbitcoin.org, mgs33@cornell.edu 6 | status: Draft 7 | type: Standards Track 8 | category: ERC 9 | created: 2018-03-07 10 | --- 11 | 12 | https://github.com/ethereum/EIPs/pull/918 13 | 14 | 15 | ### Simple Summary 16 | 17 | A specification for a standardized Mineable Token that uses a Proof of Work algorithm for distribution. 18 | 19 | ### Abstract 20 | 21 | This specification describes a method for initially locking tokens within a token contract and slowly dispensing them with a mint() function which acts like a faucet. This mint() function uses a Proof of Work algorithm in order to minimize gas fees and control the distribution rate. Additionally, standardization of mineable tokens will give rise to standardized CPU and GPU token mining software, token mining pools and other external tools in the token mining ecosystem. 22 | 23 | ### Motivation 24 | 25 | Token distribution via the ICO model and it's derivatives is susceptable to illicit behavior by human actors. Furthermore, new token projects are centralized because a single entity must handle and control all of the initial coins and all of the the raised ICO money. By distributing tokens via an 'Initial Mining Offering' (or IMO), the ownership of the token contract no longer belongs with the deployer at all and the deployer is 'just another user.' As a result, investor risk exposure utilizing a mined token distribution model is significantly diminished. This standard is intended to be standalone, allowing maximum interoperability with ERC20, ERC721, and others. 26 | 27 | ### Specification 28 | 29 | #### Interface 30 | The general behavioral specification includes a primary function that defines the token minting operation, an optional merged minting operation for issuing multiple tokens, getters for challenge number, mining difficulty, mining target and current reward, and finally a Mint event, to be emitted upon successful solution validation and token issuance. At a minimum, contracts must adhere to this interface (save the optional merge operation). It is recommended that contracts interface with the more behaviorally defined Abstract Contract described below, in order to leverage a more defined construct, allowing for easier external implementations via overridden phased functions. (see 'Abstract Contract' below) 31 | 32 | ``` js 33 | interface EIP918Interface { 34 | 35 | function mint(uint256 nonce, bytes32 challenge_digest) public returns (bool success); 36 | 37 | function getChallengeNumber() public constant returns (bytes32); 38 | 39 | function getMiningDifficulty() public constant returns (uint); 40 | 41 | function getMiningTarget() public constant returns (uint); 42 | 43 | function getMiningReward() public constant returns (uint); 44 | 45 | event Mint(address indexed from, uint reward_amount, uint epochCount, bytes32 newChallengeNumber); 46 | 47 | // Optional 48 | function merge(uint256 nonce, bytes32 challenge_digest, address[] mineTokens) public returns (bool success); 49 | 50 | } 51 | ``` 52 | 53 | #### Abstract Contract 54 | 55 | The Abstract Contract adheres to the EIP918 Interface and extends behavioral definition through the introduction of 4 internal phases of token mining and minting: hash, reward, epoch and adjust difficulty, all called during the mint() operation. This construct provides a balance between being too general for use while providing amply room for multiple mined implementation types. 56 | 57 | ### Fields 58 | 59 | #### challengeNumber 60 | The current challenge number. It is expected tha a new challenge number is generated after a new reward is minted. 61 | 62 | ``` js 63 | bytes32 public challengeNumber; 64 | ``` 65 | 66 | #### difficulty 67 | The current mining difficulty which should be adjusted via the \_adjustDifficulty minting phase 68 | 69 | ``` js 70 | uint public difficulty; 71 | ``` 72 | 73 | #### tokensMinted 74 | Cumulative counter of the total minted tokens, usually modified during the \_reward phase 75 | 76 | ``` js 77 | uint public tokensMinted; 78 | ``` 79 | 80 | ### Mining Operations 81 | 82 | #### mint 83 | 84 | Returns a flag indicating a successful hash digest verification, and reward allocation to msg.sender. In order to prevent MiTM attacks, it is recommended that the digest include a recent ethereum block hash and msg.sender's address. Once verified, the mint function calculates and delivers a mining reward to the sender and performs internal accounting operations on the contract's supply. 85 | 86 | The mint operation exists as a public function that invokes 4 separate phases, represented as internal functions \_hash, \_reward, \_newEpoch, and \_adjustDifficulty. In order to create the most flexible implementation while adhering to a necessary contract protocol, it is recommended that token implementors override the internal methods, allowing the base contract to handle their execution via mint. 87 | 88 | This externally facing function is called by miners to validate challenge digests, calculate reward, 89 | populate statistics, mutate epoch variables and adjust the solution difficulty as required. Once complete, 90 | a Mint event is emitted before returning a boolean success flag. 91 | 92 | ``` js 93 | // cumulative counter of the total minted tokens 94 | uint public tokensMinted; 95 | 96 | // track read only minting statistics 97 | struct Statistics { 98 | address lastRewardTo; 99 | uint lastRewardAmount; 100 | uint lastRewardEthBlockNumber; 101 | uint lastRewardTimestamp; 102 | } 103 | 104 | Statistics public statistics; 105 | 106 | function mint(uint256 nonce, bytes32 challenge_digest) public returns (bool success) { 107 | // perform the hash function validation 108 | _hash(nonce, challenge_digest); 109 | 110 | // calculate the current reward 111 | uint rewardAmount = _reward(); 112 | 113 | // increment the minted tokens amount 114 | tokensMinted += rewardAmount; 115 | 116 | uint epochCount = _newEpoch(nonce); 117 | 118 | _adjustDifficulty(); 119 | 120 | //populate read only diagnostics data 121 | statistics = Statistics(msg.sender, rewardAmount, block.number, now); 122 | 123 | 124 | // send Mint event indicating a successful implementation 125 | Mint(msg.sender, rewardAmount, epochCount, challengeNumber); 126 | 127 | return true; 128 | } 129 | ``` 130 | 131 | ##### *Mint Event* 132 | 133 | Upon successful verification and reward the mint method dispatches a Mint Event indicating the reward address, the reward amount, the epoch count and newest challenge number. 134 | 135 | ``` js 136 | event Mint(address indexed from, uint reward_amount, uint epochCount, bytes32 newChallengeNumber); 137 | ``` 138 | 139 | #### merge 140 | 141 | *Optional* 142 | 143 | Operationally similar to mint, except the merge function offers a list of token target addresses intended to be used to merge multiple token rewards. 144 | 145 | ``` js 146 | function merge(uint256 nonce, bytes32 challenge_digest, address[] mineTokens) public returns (bool success); 147 | ``` 148 | 149 | #### \_hash 150 | 151 | Internal interface function \_hash, meant to be overridden in implementation to define hashing algorithm and validation. Returns the validated digest 152 | 153 | ``` js 154 | function _hash(uint256 nonce, bytes32 challenge_digest) internal returns (bytes32 digest); 155 | ``` 156 | 157 | #### \_reward 158 | 159 | Internal interface function \_reward, meant to be overridden in implementation to calculate and allocate the reward amount. The reward amount must be returned by this method. 160 | 161 | ``` js 162 | function _reward() internal returns (uint); 163 | ``` 164 | 165 | #### \_newEpoch 166 | 167 | Internal interface function \_newEpoch, meant to be overridden in implementation to define a cutpoint for mutating mining variables in preparation for the next phase of mine. 168 | 169 | ``` js 170 | function _newEpoch(uint256 nonce) internal returns (uint); 171 | ``` 172 | 173 | #### \_adjustDifficulty 174 | 175 | Internal interface function \_adjustDifficulty, meant to be overridden in implementation to adjust the difficulty (via field difficulty) of the mining as required 176 | 177 | ``` js 178 | function _adjustDifficulty() internal returns (uint); 179 | ``` 180 | 181 | #### getChallengeNumber 182 | 183 | Recent ethereum block hash, used to prevent pre-mining future blocks. 184 | 185 | ``` js 186 | function getChallengeNumber() public constant returns (bytes32) 187 | ``` 188 | 189 | #### getMiningDifficulty 190 | 191 | The number of digits that the digest of the PoW solution requires which typically auto adjusts during reward generation.Return the current reward amount. Depending on the algorithm, typically rewards are divided every reward era as tokens are mined to provide scarcity. 192 | 193 | 194 | ``` js 195 | function getMiningDifficulty() public constant returns (uint) 196 | ``` 197 | 198 | #### getMiningReward 199 | 200 | Return the current reward amount. Depending on the algorithm, typically rewards are divided every reward era as tokens are mined to provide scarcity. 201 | 202 | ``` js 203 | function getMiningReward() public constant returns (uint) 204 | ``` 205 | 206 | ### Example mining function 207 | A general mining function written in python for finding a valid nonce for mined token 0xbitcoin, is as follows: 208 | ``` 209 | def mine(challenge, public_address, difficulty): 210 | while True: 211 | nonce = generate_random_number() 212 | hash1 = int(sha3.keccak_256(challenge+public_address+nonce).hexdigest(), 16) 213 | if hash1 < difficulty: 214 | return nonce, hash1 215 | ``` 216 | 217 | Once the nonce and hash1 are found, these are used to call the mint() function of the smart contract to receive a reward of tokens. 218 | 219 | ### Rationale 220 | 221 | A keccak256 algoritm does not have to be used, but it is recommended since it is a cost effective one-way algorithm to perform in the EVM and simple to perform in solidity. The nonce is the solution that miners try to find and so it is part of the hashing algorithm. A challengeNumber is also part of the hash so that future blocks cannot be mined since it acts like a random piece of data that is not revealed until a mining round starts. The msg.sender address is part of the hash so that a nonce solution is valid only for a particular Ethereum account and so the solution is not susceptible to man-in-the-middle attacks. This also allows pools to operate without being easily cheated by the miners since pools can force miners to mine using the pool's address in the hash algo. 222 | 223 | The economics of transferring electricity and hardware into mined token assets offers a flourishing community of decentralized miners the option to be involved in the Ethereum token economy directly. By voting with hashpower, an economically pegged asset to real-world resources, miners are incentivized to participate in early token trade to revamp initial costs, providing a bootstrapped stimulus mechanism between miners and early investors. 224 | 225 | One community concern for mined tokens has been around energy use without a function for securing a network. Although token mining does not secure a network, it serves the function of securing a community from corruption as it offers an alternative to centralized ICOs. Furthermore, an initial mining offering may last as little as a week, a day, or an hour at which point all of the tokens would have been minted. 226 | 227 | 228 | ### Backwards Compatibility 229 | 230 | Backwards incompatibilities are not introduced. 231 | 232 | ### Test Cases 233 | (Test cases for an implementation are mandatory for EIPs that are affecting consensus changes. Other EIPs can choose to include links to test cases if applicable.) 234 | 235 | 236 | ### Implementation 237 | 238 | Simple Example: 239 | 240 | https://github.com/0xbitcoin/EIP918-Mineable-Token/blob/master/contracts/SimpleERC918.sol 241 | 242 | Complex Examples: 243 | 244 | https://github.com/0xbitcoin/EIP918-Mineable-Token/blob/master/contracts/0xdogeExample.sol 245 | https://github.com/0xbitcoin/EIP918-Mineable-Token/blob/master/contracts/0xdogeExample2.sol 246 | https://github.com/0xbitcoin/EIP918-Mineable-Token/blob/master/contracts/0xBitcoinBase.sol 247 | 248 | 0xBitcoin Token Contract: 249 | https://etherscan.io/address/0xb6ed7644c69416d67b522e20bc294a9a9b405b31 250 | 251 | MVI OpenCL Token Miner 252 | https://github.com/mining-visualizer/MVis-tokenminer/releases 253 | 254 | PoWAdv Token Contract: 255 | https://etherscan.io/address/0x1a136ae98b49b92841562b6574d1f3f5b0044e4c 256 | 257 | 258 | ### Copyright 259 | Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). 260 | -------------------------------------------------------------------------------- /contracts/0xBitcoinBase.sol: -------------------------------------------------------------------------------- 1 | /* 2 | Implements EIP918 draft token standard: https://github.com/0xbitcoin/ERC541-Spec/blob/master/contracts/EIP541.sol 3 | .*/ 4 | pragma solidity ^0.4.18; 5 | 6 | import "./EIP20Interface.sol"; 7 | import "./AbstractERC918.sol"; 8 | import "./SafeMath.sol"; 9 | import "./ExtendedMath.sol"; 10 | import "./Owned.sol"; 11 | 12 | /** 13 | * _0xBitcoinBase Implementation used for creating ERC918, ERC20 mineable tokens using the same difficulty 14 | * adjustment, reward and hashing features of 0xBitcoin 15 | * 16 | * This complex contract implements a minimal set of behaviors (hash, reward, epoch, and difficulty adjustment) 17 | * and state required to build a Proof of Work driven mineable token. Refactoring of 0xBitcoin base code to be 18 | * used for implementing 0xbitcoin based mineable tokens 19 | * 20 | * https://github.com/ethereum/EIPs/pull/918 21 | * https://github.com/0xbitcoin/0xbitcoin-token/blob/master/contracts/_0xBitcoinToken.sol 22 | */ 23 | contract _0xBitcoinBase is AbstractERC918, EIP20Interface { 24 | using SafeMath for uint; 25 | using ExtendedMath for uint; 26 | 27 | string public symbol; 28 | string public name; 29 | uint8 public decimals; 30 | uint256 public totalSupply; 31 | uint public latestDifficultyPeriodStarted; 32 | uint public epochCount;//number of 'blocks' mined 33 | uint public baseMiningReward; 34 | uint public blocksPerReadjustment; 35 | uint public _MINIMUM_TARGET = 2**16; 36 | uint public _MAXIMUM_TARGET = 2**234; 37 | uint public rewardEra; 38 | uint public maxSupplyForEra; 39 | uint public MAX_REWARD_ERA = 39; 40 | uint public MINING_RATE_FACTOR = 60; //mint the token 60 times less often than ether 41 | //difficulty adjustment parameters- be careful modifying these 42 | uint public MAX_ADJUSTMENT_PERCENT = 100; 43 | uint public TARGET_DIVISOR = 2000; 44 | uint public QUOTIENT_LIMIT = TARGET_DIVISOR.div(2); 45 | mapping(bytes32 => bytes32) solutionForChallenge; 46 | mapping(address => mapping(address => uint)) allowed; 47 | // balances of 48 | mapping(address => uint) balances; 49 | 50 | /** 51 | * Constructor function 52 | * 53 | * Initializes contract with initial supply tokens to the creator of the contract 54 | */ 55 | function _0xBitcoinBase( 56 | string tokenSymbol, 57 | string tokenName, 58 | uint256 tokenSupply, 59 | uint8 tokenDecimals, 60 | uint initialReward, 61 | uint blocksPerDifficultyAdjustment 62 | ) public { 63 | symbol = tokenSymbol; 64 | name = tokenName; 65 | decimals = tokenDecimals; 66 | totalSupply = tokenSupply * 10**uint(decimals); 67 | baseMiningReward = initialReward; 68 | blocksPerReadjustment = blocksPerDifficultyAdjustment; 69 | // -- do not change lines below -- 70 | tokensMinted = 0; 71 | rewardEra = 0; 72 | maxSupplyForEra = totalSupply.div(2); 73 | difficulty = _MAXIMUM_TARGET; 74 | latestDifficultyPeriodStarted = block.number; 75 | _newEpoch(0); 76 | } 77 | 78 | function _hash(uint256 nonce, bytes32 challenge_digest) internal returns (bytes32 digest) { 79 | digest = keccak256(challengeNumber, msg.sender, nonce ); 80 | //the challenge digest must match the expected 81 | if (digest != challenge_digest) revert(); 82 | //the digest must be smaller than the target 83 | if(uint256(digest) > difficulty) revert(); 84 | //only allow one reward for each challenge 85 | bytes32 solution = solutionForChallenge[challengeNumber]; 86 | solutionForChallenge[challengeNumber] = digest; 87 | if(solution != 0x0) revert(); //prevent the same answer from awarding twice 88 | } 89 | 90 | //21m coins total 91 | //reward begins at 50 and is cut in half every reward era (as tokens are mined) 92 | function _reward() internal returns (uint) { 93 | //once we get half way thru the coins, only get 25 per block 94 | //every reward era, the reward amount halves. 95 | uint reward_amount = getMiningReward(); 96 | balances[msg.sender] = balances[msg.sender].add(reward_amount); 97 | return reward_amount; 98 | } 99 | 100 | function _newEpoch(uint256 nonce) internal returns (uint) { 101 | //if max supply for the era will be exceeded next reward round then enter the new era before that happens 102 | //40 is the final reward era, almost all tokens minted 103 | //once the final era is reached, more tokens will not be given out because the assert function 104 | if( tokensMinted.add(getMiningReward()) > maxSupplyForEra && rewardEra < MAX_REWARD_ERA) 105 | { 106 | rewardEra = rewardEra + 1; 107 | } 108 | //set the next minted supply at which the era will change 109 | // total supply is 2100000000000000 because of 8 decimal places 110 | maxSupplyForEra = totalSupply - totalSupply.div( 2**(rewardEra + 1)); 111 | epochCount = epochCount.add(1); 112 | //make the latest ethereum block hash a part of the next challenge for PoW to prevent pre-mining future blocks 113 | //do this last since this is a protection mechanism in the mint() function 114 | challengeNumber = block.blockhash(block.number - 1); 115 | } 116 | //DO NOT manually edit this method unless you know EXACTLY what you are doing 117 | function _adjustDifficulty() internal returns (uint) { 118 | //every so often, readjust difficulty. Dont readjust when deploying 119 | if(epochCount % blocksPerReadjustment != 0){ 120 | return difficulty; 121 | } 122 | 123 | uint ethBlocksSinceLastDifficultyPeriod = block.number - latestDifficultyPeriodStarted; 124 | //assume 360 ethereum blocks per hour 125 | //we want miners to spend 10 minutes to mine each 'block', about 60 ethereum blocks = one 0xbitcoin epoch 126 | uint epochsMined = blocksPerReadjustment; 127 | uint targetEthBlocksPerDiffPeriod = epochsMined * MINING_RATE_FACTOR; 128 | //if there were less eth blocks passed in time than expected 129 | if( ethBlocksSinceLastDifficultyPeriod < targetEthBlocksPerDiffPeriod ) 130 | { 131 | uint excess_block_pct = (targetEthBlocksPerDiffPeriod.mul(MAX_ADJUSTMENT_PERCENT)).div( ethBlocksSinceLastDifficultyPeriod ); 132 | uint excess_block_pct_extra = excess_block_pct.sub(100).limitLessThan(QUOTIENT_LIMIT); 133 | // 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. 134 | //make it harder 135 | difficulty = difficulty.sub(difficulty.div(TARGET_DIVISOR).mul(excess_block_pct_extra)); //by up to 50 % 136 | }else{ 137 | uint shortage_block_pct = (ethBlocksSinceLastDifficultyPeriod.mul(MAX_ADJUSTMENT_PERCENT)).div( targetEthBlocksPerDiffPeriod ); 138 | uint shortage_block_pct_extra = shortage_block_pct.sub(100).limitLessThan(QUOTIENT_LIMIT); //always between 0 and 1000 139 | //make it easier 140 | difficulty = difficulty.add(difficulty.div(TARGET_DIVISOR).mul(shortage_block_pct_extra)); //by up to 50 % 141 | } 142 | latestDifficultyPeriodStarted = block.number; 143 | if(difficulty < _MINIMUM_TARGET) //very difficult 144 | { 145 | difficulty = _MINIMUM_TARGET; 146 | } 147 | if(difficulty > _MAXIMUM_TARGET) //very easy 148 | { 149 | difficulty = _MAXIMUM_TARGET; 150 | } 151 | } 152 | //this is a recent ethereum block hash, used to prevent pre-mining future blocks 153 | function getChallengeNumber() public constant returns (bytes32) { 154 | return challengeNumber; 155 | } 156 | //the number of zeroes the digest of the PoW solution requires. Auto adjusts 157 | function getMiningDifficulty() public constant returns (uint) { 158 | return _MAXIMUM_TARGET.div(difficulty); 159 | } 160 | function getMiningTarget() public constant returns (uint) { 161 | return difficulty; 162 | } 163 | 164 | //21m coins total 165 | //reward begins at 50 and is cut in half every reward era (as tokens are mined) 166 | function getMiningReward() public constant returns (uint) { 167 | //once we get half way thru the coins, only get 25 per block 168 | //every reward era, the reward amount halves. 169 | return (baseMiningReward * 10**uint(decimals) ).div( 2**rewardEra ) ; 170 | } 171 | 172 | //help debug mining software 173 | function getMintDigest(uint256 nonce, bytes32 challenge_digest, bytes32 challenge_number) public view returns (bytes32 digesttest) { 174 | bytes32 digest = keccak256(challenge_number,msg.sender,nonce); 175 | return digest; 176 | } 177 | //help debug mining software 178 | function checkMintSolution(uint256 nonce, bytes32 challenge_digest, bytes32 challenge_number, uint testTarget) public view returns (bool success) { 179 | bytes32 digest = keccak256(challenge_number,msg.sender,nonce); 180 | if(uint256(digest) > testTarget) revert(); 181 | return (digest == challenge_digest); 182 | } 183 | // ------------------------------------------------------------------------ 184 | // Total supply 185 | // ------------------------------------------------------------------------ 186 | function totalSupply() public constant returns (uint) { 187 | return totalSupply - balances[address(0)]; 188 | } 189 | // ------------------------------------------------------------------------ 190 | // Get the token balance for account `tokenOwner` 191 | // ------------------------------------------------------------------------ 192 | function balanceOf(address tokenOwner) public constant returns (uint balance) { 193 | return balances[tokenOwner]; 194 | } 195 | // ------------------------------------------------------------------------ 196 | // Transfer the balance from token owner's account to `to` account 197 | // - Owner's account must have sufficient balance to transfer 198 | // - 0 value transfers are allowed 199 | // ------------------------------------------------------------------------ 200 | function transfer(address to, uint tokens) public returns (bool success) { 201 | balances[msg.sender] = balances[msg.sender].sub(tokens); 202 | balances[to] = balances[to].add(tokens); 203 | Transfer(msg.sender, to, tokens); 204 | return true; 205 | } 206 | // ------------------------------------------------------------------------ 207 | // Token owner can approve for `spender` to transferFrom(...) `tokens` 208 | // from the token owner's account 209 | // 210 | // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md 211 | // recommends that there are no checks for the approval double-spend attack 212 | // as this should be implemented in user interfaces 213 | // ------------------------------------------------------------------------ 214 | function approve(address spender, uint tokens) public returns (bool success) { 215 | allowed[msg.sender][spender] = tokens; 216 | Approval(msg.sender, spender, tokens); 217 | return true; 218 | } 219 | // ------------------------------------------------------------------------ 220 | // Transfer `tokens` from the `from` account to the `to` account 221 | // 222 | // The calling account must already have sufficient tokens approve(...)-d 223 | // for spending from the `from` account and 224 | // - From account must have sufficient balance to transfer 225 | // - Spender must have sufficient allowance to transfer 226 | // - 0 value transfers are allowed 227 | // ------------------------------------------------------------------------ 228 | function transferFrom(address from, address to, uint tokens) public returns (bool success) { 229 | balances[from] = balances[from].sub(tokens); 230 | allowed[from][msg.sender] = allowed[from][msg.sender].sub(tokens); 231 | balances[to] = balances[to].add(tokens); 232 | Transfer(from, to, tokens); 233 | return true; 234 | } 235 | // ------------------------------------------------------------------------ 236 | // Returns the amount of tokens approved by the owner that can be 237 | // transferred to the spender's account 238 | // ------------------------------------------------------------------------ 239 | function allowance(address tokenOwner, address spender) public constant returns (uint remaining) { 240 | return allowed[tokenOwner][spender]; 241 | } 242 | 243 | // ------------------------------------------------------------------------ 244 | // Token owner can approve for `spender` to transferFrom(...) `tokens` 245 | // from the token owner's account. The `spender` contract function 246 | // `receiveApproval(...)` is then executed 247 | // ------------------------------------------------------------------------ 248 | function approveAndCall(address spender, uint tokens, bytes data) public returns (bool success) { 249 | allowed[msg.sender][spender] = tokens; 250 | Approval(msg.sender, spender, tokens); 251 | ApproveAndCallFallBack(spender).receiveApproval(msg.sender, tokens, this, data); 252 | return true; 253 | } 254 | 255 | // ------------------------------------------------------------------------ 256 | // Don't accept ETH 257 | // ------------------------------------------------------------------------ 258 | function () public payable { 259 | revert(); 260 | } 261 | 262 | } 263 | 264 | contract ApproveAndCallFallBack { 265 | function receiveApproval(address from, uint256 tokens, address token, bytes data) public; 266 | } 267 | -------------------------------------------------------------------------------- /contracts/EIP918_Example.sol: -------------------------------------------------------------------------------- 1 | /* 2 | Implements EIP918 token standard 3 | .*/ 4 | 5 | 6 | pragma solidity ^0.4.18; 7 | 8 | import "./EIP20Interface.sol"; 9 | 10 | import "./EIP918Interface.sol"; 11 | 12 | import "./SafeMath.sol"; 13 | 14 | import "./ExtendedMath.sol"; 15 | 16 | import "./Owned.sol"; 17 | 18 | 19 | contract EIP918_Token_Sample is EIP918Interface,EIP20Interface, Owned { 20 | 21 | using SafeMath for uint; 22 | using ExtendedMath for uint; 23 | 24 | 25 | string public symbol; 26 | 27 | string public name; 28 | 29 | uint8 public decimals; 30 | 31 | uint256 public totalSupply; 32 | 33 | 34 | 35 | uint public latestDifficultyPeriodStarted; 36 | 37 | 38 | 39 | uint public epochCount;//number of 'blocks' mined 40 | 41 | uint public BASE_MINING_REWARD = 50; 42 | 43 | uint public _BLOCKS_PER_READJUSTMENT = 1024; 44 | 45 | 46 | uint public _MINIMUM_TARGET = 2**16; 47 | 48 | 49 | //a big number is easier ; just find a solution that is smaller 50 | //uint public _MAXIMUM_TARGET = 2**224; bitcoin uses 224 51 | uint public _MAXIMUM_TARGET = 2**234; 52 | 53 | 54 | 55 | uint public miningTarget; 56 | 57 | bytes32 public challengeNumber; //generate a new one when a new reward is minted 58 | 59 | 60 | 61 | uint public rewardEra; 62 | uint public maxSupplyForEra; 63 | 64 | uint public MAX_REWARD_ERA = 39; 65 | uint public MINING_RATE_FACTOR = 60; //mint the token 60 times less often than ether 66 | 67 | address public lastRewardTo; 68 | uint public lastRewardAmount; 69 | uint public lastRewardEthBlockNumber; 70 | 71 | 72 | //difficulty adjustment parameters- be careful modifying these 73 | uint public MAX_ADJUSTMENT_PERCENT = 100; 74 | uint public TARGET_DIVISOR = 2000; 75 | uint public QUOTIENT_LIMIT = TARGET_DIVISOR.div(2); 76 | 77 | 78 | 79 | bool locked = false; 80 | 81 | mapping(bytes32 => bytes32) solutionForChallenge; 82 | 83 | uint public tokensMinted; 84 | 85 | mapping(address => uint) balances; 86 | 87 | 88 | mapping(address => mapping(address => uint)) allowed; 89 | 90 | 91 | event Mint(address indexed from, uint reward_amount, uint epochCount, bytes32 newChallengeNumber); 92 | 93 | // ------------------------------------------------------------------------ 94 | 95 | // Constructor 96 | 97 | // ------------------------------------------------------------------------ 98 | 99 | function EIP918_Token_Sample() public onlyOwner{ 100 | 101 | 102 | 103 | symbol = "???"; 104 | 105 | name = "???"; 106 | 107 | decimals = 8; 108 | 109 | totalSupply = 21000000 * 10**uint(decimals); 110 | 111 | 112 | 113 | 114 | 115 | 116 | // -- do not change lines below -- 117 | if(locked) revert(); 118 | locked = true; 119 | 120 | tokensMinted = 0; 121 | 122 | rewardEra = 0; 123 | maxSupplyForEra = totalSupply.div(2); 124 | 125 | miningTarget = _MAXIMUM_TARGET; 126 | 127 | latestDifficultyPeriodStarted = block.number; 128 | 129 | _startNewMiningEpoch(); 130 | 131 | 132 | //The owner gets nothing! You must mine this ERC20 token 133 | //balances[owner] = totalSupply; 134 | //Transfer(address(0), owner, totalSupply); 135 | 136 | } 137 | 138 | 139 | 140 | 141 | function mint(uint256 nonce, bytes32 challenge_digest) public returns (bool success) { 142 | 143 | 144 | //the PoW must contain work that includes a recent ethereum block hash (challenge number) and the msg.sender's address to prevent MITM attacks 145 | bytes32 digest = keccak256(challengeNumber, msg.sender, nonce ); 146 | 147 | //the challenge digest must match the expected 148 | if (digest != challenge_digest) revert(); 149 | 150 | //the digest must be smaller than the target 151 | if(uint256(digest) > miningTarget) revert(); 152 | 153 | 154 | //only allow one reward for each challenge 155 | bytes32 solution = solutionForChallenge[challengeNumber]; 156 | solutionForChallenge[challengeNumber] = digest; 157 | if(solution != 0x0) revert(); //prevent the same answer from awarding twice 158 | 159 | 160 | uint reward_amount = getMiningReward(); 161 | 162 | balances[msg.sender] = balances[msg.sender].add(reward_amount); 163 | 164 | tokensMinted = tokensMinted.add(reward_amount); 165 | 166 | 167 | //Cannot mint more tokens than there are 168 | assert(tokensMinted <= maxSupplyForEra); 169 | 170 | //set readonly diagnostics data 171 | lastRewardTo = msg.sender; 172 | lastRewardAmount = reward_amount; 173 | lastRewardEthBlockNumber = block.number; 174 | 175 | 176 | _startNewMiningEpoch(); 177 | 178 | Mint(msg.sender, reward_amount, epochCount, challengeNumber ); 179 | 180 | return true; 181 | 182 | } 183 | 184 | 185 | 186 | //DO NOT manually edit this method unless you know EXACTLY what you are doing 187 | function _startNewMiningEpoch() internal { 188 | 189 | //if max supply for the era will be exceeded next reward round then enter the new era before that happens 190 | 191 | //40 is the final reward era, almost all tokens minted 192 | //once the final era is reached, more tokens will not be given out because the assert function 193 | if( tokensMinted.add(getMiningReward()) > maxSupplyForEra && rewardEra < MAX_REWARD_ERA) 194 | { 195 | rewardEra = rewardEra + 1; 196 | } 197 | 198 | //set the next minted supply at which the era will change 199 | // total supply is 2100000000000000 because of 8 decimal places 200 | maxSupplyForEra = totalSupply - totalSupply.div( 2**(rewardEra + 1)); 201 | 202 | epochCount = epochCount.add(1); 203 | 204 | //every so often, readjust difficulty. Dont readjust when deploying 205 | if(epochCount % _BLOCKS_PER_READJUSTMENT == 0) 206 | { 207 | _reAdjustDifficulty(); 208 | } 209 | 210 | 211 | //make the latest ethereum block hash a part of the next challenge for PoW to prevent pre-mining future blocks 212 | //do this last since this is a protection mechanism in the mint() function 213 | challengeNumber = block.blockhash(block.number - 1); 214 | 215 | 216 | } 217 | 218 | 219 | 220 | 221 | 222 | //DO NOT manually edit this method unless you know EXACTLY what you are doing 223 | function _reAdjustDifficulty() internal { 224 | 225 | 226 | uint ethBlocksSinceLastDifficultyPeriod = block.number - latestDifficultyPeriodStarted; 227 | //assume 360 ethereum blocks per hour 228 | 229 | //we want miners to spend 10 minutes to mine each 'block', about 60 ethereum blocks = one 0xbitcoin epoch 230 | uint epochsMined = _BLOCKS_PER_READJUSTMENT; 231 | 232 | uint targetEthBlocksPerDiffPeriod = epochsMined * MINING_RATE_FACTOR; 233 | 234 | 235 | 236 | 237 | //if there were less eth blocks passed in time than expected 238 | if( ethBlocksSinceLastDifficultyPeriod < targetEthBlocksPerDiffPeriod ) 239 | { 240 | uint excess_block_pct = (targetEthBlocksPerDiffPeriod.mul(MAX_ADJUSTMENT_PERCENT)).div( ethBlocksSinceLastDifficultyPeriod ); 241 | 242 | uint excess_block_pct_extra = excess_block_pct.sub(100).limitLessThan(QUOTIENT_LIMIT); 243 | // 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. 244 | 245 | //make it harder 246 | miningTarget = miningTarget.sub(miningTarget.div(TARGET_DIVISOR).mul(excess_block_pct_extra)); //by up to 50 % 247 | }else{ 248 | uint shortage_block_pct = (ethBlocksSinceLastDifficultyPeriod.mul(MAX_ADJUSTMENT_PERCENT)).div( targetEthBlocksPerDiffPeriod ); 249 | 250 | uint shortage_block_pct_extra = shortage_block_pct.sub(100).limitLessThan(QUOTIENT_LIMIT); //always between 0 and 1000 251 | 252 | //make it easier 253 | miningTarget = miningTarget.add(miningTarget.div(TARGET_DIVISOR).mul(shortage_block_pct_extra)); //by up to 50 % 254 | } 255 | 256 | 257 | 258 | latestDifficultyPeriodStarted = block.number; 259 | 260 | if(miningTarget < _MINIMUM_TARGET) //very difficult 261 | { 262 | miningTarget = _MINIMUM_TARGET; 263 | } 264 | 265 | if(miningTarget > _MAXIMUM_TARGET) //very easy 266 | { 267 | miningTarget = _MAXIMUM_TARGET; 268 | } 269 | } 270 | 271 | 272 | //this is a recent ethereum block hash, used to prevent pre-mining future blocks 273 | function getChallengeNumber() public constant returns (bytes32) { 274 | return challengeNumber; 275 | } 276 | 277 | //the number of zeroes the digest of the PoW solution requires. Auto adjusts 278 | function getMiningDifficulty() public constant returns (uint) { 279 | return _MAXIMUM_TARGET.div(miningTarget); 280 | } 281 | 282 | function getMiningTarget() public constant returns (uint) { 283 | return miningTarget; 284 | } 285 | 286 | 287 | 288 | //21m coins total 289 | //reward begins at 50 and is cut in half every reward era (as tokens are mined) 290 | function getMiningReward() public constant returns (uint) { 291 | //once we get half way thru the coins, only get 25 per block 292 | 293 | //every reward era, the reward amount halves. 294 | 295 | return (BASE_MINING_REWARD * 10**uint(decimals) ).div( 2**rewardEra ) ; 296 | 297 | } 298 | 299 | //help debug mining software 300 | function getMintDigest(uint256 nonce, bytes32 challenge_digest, bytes32 challenge_number) public view returns (bytes32 digesttest) { 301 | 302 | bytes32 digest = keccak256(challenge_number,msg.sender,nonce); 303 | 304 | return digest; 305 | 306 | } 307 | 308 | //help debug mining software 309 | function checkMintSolution(uint256 nonce, bytes32 challenge_digest, bytes32 challenge_number, uint testTarget) public view returns (bool success) { 310 | 311 | bytes32 digest = keccak256(challenge_number,msg.sender,nonce); 312 | 313 | if(uint256(digest) > testTarget) revert(); 314 | 315 | return (digest == challenge_digest); 316 | 317 | } 318 | 319 | 320 | 321 | // ------------------------------------------------------------------------ 322 | 323 | // Total supply 324 | 325 | // ------------------------------------------------------------------------ 326 | 327 | function totalSupply() public constant returns (uint) { 328 | 329 | return totalSupply - balances[address(0)]; 330 | 331 | } 332 | 333 | 334 | 335 | // ------------------------------------------------------------------------ 336 | 337 | // Get the token balance for account `tokenOwner` 338 | 339 | // ------------------------------------------------------------------------ 340 | 341 | function balanceOf(address tokenOwner) public constant returns (uint balance) { 342 | 343 | return balances[tokenOwner]; 344 | 345 | } 346 | 347 | 348 | 349 | // ------------------------------------------------------------------------ 350 | 351 | // Transfer the balance from token owner's account to `to` account 352 | 353 | // - Owner's account must have sufficient balance to transfer 354 | 355 | // - 0 value transfers are allowed 356 | 357 | // ------------------------------------------------------------------------ 358 | 359 | function transfer(address to, uint tokens) public returns (bool success) { 360 | 361 | balances[msg.sender] = balances[msg.sender].sub(tokens); 362 | 363 | balances[to] = balances[to].add(tokens); 364 | 365 | Transfer(msg.sender, to, tokens); 366 | 367 | return true; 368 | 369 | } 370 | 371 | 372 | 373 | // ------------------------------------------------------------------------ 374 | 375 | // Token owner can approve for `spender` to transferFrom(...) `tokens` 376 | 377 | // from the token owner's account 378 | 379 | // 380 | 381 | // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md 382 | 383 | // recommends that there are no checks for the approval double-spend attack 384 | 385 | // as this should be implemented in user interfaces 386 | 387 | // ------------------------------------------------------------------------ 388 | 389 | function approve(address spender, uint tokens) public returns (bool success) { 390 | 391 | allowed[msg.sender][spender] = tokens; 392 | 393 | Approval(msg.sender, spender, tokens); 394 | 395 | return true; 396 | 397 | } 398 | 399 | 400 | 401 | // ------------------------------------------------------------------------ 402 | 403 | // Transfer `tokens` from the `from` account to the `to` account 404 | 405 | // 406 | 407 | // The calling account must already have sufficient tokens approve(...)-d 408 | 409 | // for spending from the `from` account and 410 | 411 | // - From account must have sufficient balance to transfer 412 | 413 | // - Spender must have sufficient allowance to transfer 414 | 415 | // - 0 value transfers are allowed 416 | 417 | // ------------------------------------------------------------------------ 418 | 419 | function transferFrom(address from, address to, uint tokens) public returns (bool success) { 420 | 421 | balances[from] = balances[from].sub(tokens); 422 | 423 | allowed[from][msg.sender] = allowed[from][msg.sender].sub(tokens); 424 | 425 | balances[to] = balances[to].add(tokens); 426 | 427 | Transfer(from, to, tokens); 428 | 429 | return true; 430 | 431 | } 432 | 433 | 434 | 435 | // ------------------------------------------------------------------------ 436 | 437 | // Returns the amount of tokens approved by the owner that can be 438 | 439 | // transferred to the spender's account 440 | 441 | // ------------------------------------------------------------------------ 442 | 443 | function allowance(address tokenOwner, address spender) public constant returns (uint remaining) { 444 | 445 | return allowed[tokenOwner][spender]; 446 | 447 | } 448 | 449 | 450 | 451 | // ------------------------------------------------------------------------ 452 | 453 | // Token owner can approve for `spender` to transferFrom(...) `tokens` 454 | 455 | // from the token owner's account. The `spender` contract function 456 | 457 | // `receiveApproval(...)` is then executed 458 | 459 | // ------------------------------------------------------------------------ 460 | 461 | function approveAndCall(address spender, uint tokens, bytes data) public returns (bool success) { 462 | 463 | allowed[msg.sender][spender] = tokens; 464 | 465 | Approval(msg.sender, spender, tokens); 466 | 467 | ApproveAndCallFallBack(spender).receiveApproval(msg.sender, tokens, this, data); 468 | 469 | return true; 470 | 471 | } 472 | 473 | 474 | 475 | // ------------------------------------------------------------------------ 476 | 477 | // Don't accept ETH 478 | 479 | // ------------------------------------------------------------------------ 480 | 481 | function () public payable { 482 | 483 | revert(); 484 | 485 | } 486 | 487 | 488 | 489 | // ------------------------------------------------------------------------ 490 | 491 | // Owner can transfer out any accidentally sent ERC20 tokens 492 | 493 | // ------------------------------------------------------------------------ 494 | 495 | function transferAnyERC20Token(address tokenAddress, uint tokens) public onlyOwner returns (bool success) { 496 | 497 | return EIP20Interface(tokenAddress).transfer(owner, tokens); 498 | 499 | } 500 | 501 | } 502 | 503 | 504 | 505 | contract ApproveAndCallFallBack { 506 | 507 | function receiveApproval(address from, uint256 tokens, address token, bytes data) public; 508 | 509 | } 510 | --------------------------------------------------------------------------------