/ EIPS / eip-918.md
eip-918.md
  1  ---
  2  eip: 918
  3  title: Mineable Token Standard
  4  author: Jay Logelin <jlogelin@fas.harvard.edu>, Infernal_toast <admin@0xbitcoin.org>, Michael Seiler <mgs33@cornell.edu>, Brandon Grill <bg2655@columbia.edu>
  5  type: Standards Track
  6  category: ERC
  7  status: Draft
  8  created: 2018-03-07
  9  ---
 10   
 11  ### Simple Summary
 12  
 13  A specification for a standardized Mineable Token that uses a Proof of Work algorithm for distribution. 
 14  
 15  ### Abstract
 16  
 17  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.
 18  
 19  ### Motivation
 20  
 21  Token distribution via the ICO model and its derivatives is susceptible 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 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.
 22  
 23  ### Specification
 24  
 25  #### Interface
 26  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)
 27  
 28  ``` solidity
 29  contract ERC918  {
 30     
 31     function mint(uint256 nonce) public returns (bool success);
 32  
 33     function getAdjustmentInterval() public view returns (uint);
 34  
 35     function getChallengeNumber() public view returns (bytes32);
 36  
 37     function getMiningDifficulty() public view returns (uint);
 38  
 39     function getMiningTarget() public view returns (uint);
 40  
 41     function getMiningReward() public view returns (uint);
 42  
 43     function hash(uint256 _nonce, address _minter) public returns (bytes32 digest);
 44  
 45     function _reward(address _minter) internal returns (uint);
 46      
 47     function _epoch() internal returns (uint);
 48      
 49     function _adjustDifficulty() internal returns (uint);
 50  
 51     event Mint(address indexed from, uint rewardAmount, uint epochCount, bytes32 newChallengeNumber);
 52  }
 53  ```
 54  
 55  #### Abstract Contract
 56  
 57  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 ample room for multiple mined implementation types.
 58  
 59  ### Fields
 60  
 61  #### adjustmentInterval
 62  The amount of time between difficulty adjustments in seconds.
 63  
 64  ``` solidity
 65  bytes32 public adjustmentInterval;
 66  ```
 67  
 68  #### challengeNumber
 69  The current challenge number. It is expected that a new challenge number is generated after a new reward is minted.
 70  
 71  ``` solidity
 72  bytes32 public challengeNumber;
 73  ```
 74  
 75  #### difficulty
 76  The current mining difficulty which should be adjusted via the \_adjustDifficulty minting phase
 77  
 78  ``` solidity
 79  uint public difficulty;
 80  ```
 81  
 82  #### tokensMinted
 83  Cumulative counter of the total minted tokens, usually modified during the \_reward phase
 84  
 85  ``` solidity
 86  uint public tokensMinted;
 87  ```
 88  
 89  #### epochCount
 90  Number of 'blocks' mined
 91  
 92  ``` solidity
 93  uint public epochCount;
 94  ```
 95  
 96  ### Mining Operations
 97  
 98  #### mint
 99  
100  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.
101  
102  The mint operation exists as a public function that invokes 4 separate phases, represented as 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.
103  
104  This externally facing function is called by miners to validate challenge digests, calculate reward,
105  populate statistics, mutate epoch variables and adjust the solution difficulty as required. Once complete,
106  a Mint event is emitted before returning a boolean success flag.
107  
108  ``` solidity
109  contract AbstractERC918 is EIP918Interface {
110  
111      // the amount of time between difficulty adjustments
112      uint public adjustmentInterval;
113       
114      // generate a new challenge number after a new reward is minted
115      bytes32 public challengeNumber;
116      
117      // the current mining target
118      uint public miningTarget;
119  
120      // cumulative counter of the total minted tokens
121      uint public tokensMinted;
122  
123      // number of blocks per difficulty readjustment
124      uint public blocksPerReadjustment;
125  
126      //number of 'blocks' mined
127      uint public epochCount;
128     
129      /*
130       * Externally facing mint function that is called by miners to validate challenge digests, calculate reward,
131       * populate statistics, mutate epoch variables and adjust the solution difficulty as required. Once complete,
132       * a Mint event is emitted before returning a success indicator.
133       **/
134      function mint(uint256 nonce) public returns (bool success) {
135          require(msg.sender != address(0));
136  
137          // perform the hash function validation
138          hash(nonce);
139          
140          // calculate the current reward
141          uint rewardAmount = _reward();
142          
143          // increment the minted tokens amount
144          tokensMinted += rewardAmount;
145          
146          epochCount = _epoch();
147  
148          //every so often, readjust difficulty. Don't readjust when deploying
149          if(epochCount % blocksPerReadjustment == 0){
150              _adjustDifficulty();
151          }
152         
153          // send Mint event indicating a successful implementation
154          emit Mint(msg.sender, rewardAmount, epochCount, challengeNumber);
155          
156          return true;
157      }
158  }
159  ```
160  
161  ##### *Mint Event*
162  
163  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.
164  
165  ``` solidity
166  event Mint(address indexed from, uint reward_amount, uint epochCount, bytes32 newChallengeNumber);
167  ```
168  
169  #### hash
170  
171  Public interface function hash, meant to be overridden in implementation to define hashing algorithm and validation. Returns the validated digest
172  
173  ``` solidity
174  function hash(uint256 nonce) public returns (bytes32 digest);
175  ```
176  
177  #### \_reward
178  
179  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.
180  
181  ``` solidity
182  function _reward() internal returns (uint);
183  ```
184  
185  #### \_newEpoch
186  
187  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.
188  
189  ``` solidity
190  function _newEpoch(uint256 nonce) internal returns (uint);
191  ```
192   
193  #### \_adjustDifficulty
194   
195  Internal interface function \_adjustDifficulty, meant to be overridden in implementation to adjust the difficulty (via field difficulty) of the mining as required
196  
197  ``` solidity
198  function _adjustDifficulty() internal returns (uint);
199  ```
200  
201  #### getAdjustmentInterval
202  
203  The amount of time, in seconds, between difficulty adjustment operations.
204  
205  ``` solidity
206  function getAdjustmentInterval() public view returns (uint);
207  ```
208  
209  #### getChallengeNumber
210  
211  Recent ethereum block hash, used to prevent pre-mining future blocks.
212  
213  ``` solidity
214  function getChallengeNumber() public view returns (bytes32);
215  ```
216  
217  #### getMiningDifficulty
218  
219  The number of digits that the digest of the PoW solution requires which typically auto adjusts during reward generation.
220  
221  ``` solidity
222  function getMiningDifficulty() public view returns (uint)
223  ```
224  
225  #### getMiningReward
226  
227  Return the current reward amount. Depending on the algorithm, typically rewards are divided every reward era as tokens are mined to provide scarcity.
228  
229  ``` solidity
230  function getMiningReward() public view returns (uint)
231  ```
232  
233  ### Example mining function
234  A general mining function written in python for finding a valid nonce for keccak256 mined token, is as follows: 
235  ``` python
236  def generate_nonce():
237    myhex =  b'%064x' % getrandbits(32*8)
238    return codecs.decode(myhex, 'hex_codec')
239    
240  def mine(challenge, public_address, difficulty):
241    while True:
242      nonce = generate_nonce()
243      hash1 = int(sha3.keccak_256(challenge+public_address+nonce).hexdigest(), 16)
244      if hash1 < difficulty:
245        return nonce, hash1
246  ```
247  
248  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.
249  
250  ### Merged Mining Extension (Optional)
251  In order to provide support for merge mining multiple tokens, an optional merged mining extension can be implemented as part of the ERC918 standard. It is important to note that the following function will only properly work if the base contracts use tx.origin instead of msg.sender when applying rewards. If not the rewarded tokens will be sent to the calling contract and not the end user.
252  
253  ``` solidity
254  /**
255   * @title ERC-918 Mineable Token Standard, optional merged mining functionality
256   * @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-918.md
257   * 
258   */
259  contract ERC918Merged is AbstractERC918 {
260      /*
261       * @notice Externally facing merge function that is called by miners to validate challenge digests, calculate reward,
262       * populate statistics, mutate state variables and adjust the solution difficulty as required. Additionally, the
263       * merge function takes an array of target token addresses to be used in merged rewards. Once complete,
264       * a Mint event is emitted before returning a success indicator.
265       *
266       * @param _nonce the solution nonce
267       **/
268      function merge(uint256 _nonce, address[] _mineTokens) public returns (bool) {
269        for (uint i = 0; i < _mineTokens.length; i++) {
270          address tokenAddress = _mineTokens[i];
271          ERC918Interface(tokenAddress).mint(_nonce);
272        }
273      }
274  
275      /*
276       * @notice Externally facing merge function kept for backwards compatibility with previous definition
277       *
278       * @param _nonce the solution nonce
279       * @param _challenge_digest the keccak256 encoded challenge number + message sender + solution nonce
280       **/
281       function merge(uint256 _nonce, bytes32 _challenge_digest, address[] _mineTokens) public returns (bool) {
282         //the challenge digest must match the expected
283         bytes32 digest = keccak256( abi.encodePacked(challengeNumber, msg.sender, _nonce) );
284         require(digest == _challenge_digest, "Challenge digest does not match expected digest on token contract [ ERC918Merged.mint() ]");
285         return merge(_nonce, _mineTokens);
286       }
287  }
288  ```
289  
290  ### Delegated Minting Extension (Optional)
291  In order to facilitate a third party minting submission paradigm, such as the case of miners submitting solutions to a pool operator and/or system, a delegated minting extension can be used to allow pool accounts submit solutions on the behalf of a user, so the miner can avoid directly paying Ethereum transaction costs. This is performed by an off chain mining account packaging and signing a standardized mint solution packet and sending it to a pool or 3rd party to be submitted.
292  
293  The ERC918 Mineable Mint Packet Metadata should be prepared using following schema:
294  ``` solidity
295  {
296      "title": "Mineable Mint Packet Metadata",
297      "type": "object",
298      "properties": {
299          "nonce": {
300              "type": "string",
301              "description": "Identifies the target solution nonce",
302          },
303          "origin": {
304              "type": "string",
305              "description": "Identifies the original user that mined the solution nonce",
306          },
307          "signature": {
308              "type": "string",
309              "description": "The signed hash of tightly packed variables sha3('delegatedMintHashing(uint256,address)')+nonce+origin_account",
310          }
311      }
312  }
313  ```
314  The preparation of a mineable mint packet on a JavaScript client would appear as follows:
315  
316  ``` solidity
317  function prepareDelegatedMintTxn(nonce, account) {
318    var functionSig = web3.utils.sha3("delegatedMintHashing(uint256,address)").substring(0,10)
319    var data = web3.utils.soliditySha3( functionSig, nonce, account.address )
320    var sig = web3.eth.accounts.sign(web3.utils.toHex(data), account.privateKey )
321    // prepare the mint packet
322    var packet = {}
323    packet.nonce = nonce
324    packet.origin = account.address
325    packet.signature = sig.signature
326    // deliver resulting JSON packet to pool or third party
327    var mineableMintPacket = JSON.stringify(packet, null, 4)
328    /* todo: send mineableMintPacket to submitter */
329    ...
330  }
331  ```
332  Once the packet is prepared and formatted it can then be routed to a third party that will submit the transaction to the contract's delegatedMint() function, thereby paying for the transaction gas and receiving the resulting tokens. The pool/third party must then manually payback the minted tokens minus fees to the original minter.
333  
334  The following code sample exemplifies third party packet relaying:
335  ``` solidity
336  //received by minter
337  var mineableMintPacket = ...
338  var packet = JSON.parse(mineableMintPacket)
339  erc918MineableToken.delegatedMint(packet.nonce, packet.origin, packet.signature)
340  ```
341  The Delegated Mint Extension expands upon ERC918 realized as a sub-contract:
342  ``` js
343  import 'openzeppelin-solidity/contracts/contracts/cryptography/ECDSA.sol';
344  
345  contract ERC918DelegatedMint is AbstractERC918, ECDSA {
346     /**
347       * @notice Hash (keccak256) of the payload used by delegatedMint
348       * @param _nonce the golden nonce
349       * @param _origin the original minter
350       * @param _signature the original minter's eliptical curve signature
351       */
352      function delegatedMint(uint256 _nonce, address _origin, bytes _signature) public returns (bool success) {
353          bytes32 hashedTx = delegatedMintHashing(_nonce, _origin);
354          address minter = recover(hashedTx, _signature);
355          require(minter == _origin, "Origin minter address does not match recovered signature address [ AbstractERC918.delegatedMint() ]");
356          require(minter != address(0), "Invalid minter address recovered from signature [ ERC918DelegatedMint.delegatedMint() ]");
357          success = mintInternal(_nonce, minter);
358      }
359  
360      /**
361       * @notice Hash (keccak256) of the payload used by delegatedMint
362       * @param _nonce the golden nonce
363       * @param _origin the original minter
364       */
365      function delegatedMintHashing(uint256 _nonce, address _origin) public pure returns (bytes32) {
366          /* "0x7b36737a": delegatedMintHashing(uint256,address) */
367          return toEthSignedMessageHash(keccak256(abi.encodePacked( bytes4(0x7b36737a), _nonce, _origin)));
368      }
369  }
370  ```
371  
372  ### Mineable Token Metadata (Optional)
373  In order to provide for richer and potentially mutable metadata for a particular Mineable Token, it is more viable to offer an off-chain reference to said data. This requires the implementation of a single interface method 'metadataURI()' that returns a JSON string encoded with the string fields symbol, name, description, website, image, and type.
374  
375  Solidity interface for Mineable Token Metadata:
376  ``` solidity
377  /**
378   * @title ERC-918 Mineable Token Standard, optional metadata extension
379   * @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-918.md
380   * 
381   */
382  interface ERC918Metadata is AbstractERC918 {
383      /**
384       * @notice A distinct Uniform Resource Identifier (URI) for a mineable asset.
385       */
386      function metadataURI() external view returns (string);
387  }
388  ```
389  
390  Mineable Token Metadata JSON schema definition:
391  ``` solidity
392  {
393      "title": "Mineable Token Metadata",
394      "type": "object",
395      "properties": {
396          "symbol": {
397              "type": "string",
398              "description": "Identifies the Mineable Token's symbol",
399          },
400          "name": {
401              "type": "string",
402              "description": "Identifies the Mineable Token's name",
403          },
404          "description": {
405              "type": "string",
406              "description": "Identifies the Mineable Token's long description",
407          },
408          "website": {
409              "type": "string",
410              "description": "Identifies the Mineable Token's homepage URI",
411          },
412          "image": {
413              "type": "string",
414              "description": "Identifies the Mineable Token's image URI",
415          },
416          "type": {
417              "type": "string",
418              "description": "Identifies the Mineable Token's hash algorithm ( ie.keccak256 ) used to encode the solution",
419          }
420      }
421  }
422  ```
423  
424  ### Rationale
425  
426  The solidity keccak256 algorithm 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 algorithm.  
427  
428  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 hash power, 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.
429  
430  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.
431  
432  
433  ### Backwards Compatibility
434  Earlier versions of this standard incorporated a redundant 'challenge_digest' parameter on the mint() function that hash-encoded the packed variables challengeNumber, msg.sender and nonce. It was decided that this could be removed from the standard to help minimize processing and thereby gas usage during mint operations. However, in the name of interoperability with existing mining programs and pool software the following contract can be added to the inheritance tree:
435  
436  ``` solidity
437  /**
438   * @title ERC-918 Mineable Token Standard, optional backwards compatibility function
439   * @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-918.md
440   * 
441   */
442  contract ERC918BackwardsCompatible is AbstractERC918 {
443  
444      /*
445       * @notice Externally facing mint function kept for backwards compatibility with previous mint() definition
446       * @param _nonce the solution nonce
447       * @param _challenge_digest the keccak256 encoded challenge number + message sender + solution nonce
448       **/
449      function mint(uint256 _nonce, bytes32 _challenge_digest) public returns (bool success) {
450          //the challenge digest must match the expected
451          bytes32 digest = keccak256( abi.encodePacked(challengeNumber, msg.sender, _nonce) );
452          require(digest == _challenge_digest, "Challenge digest does not match expected digest on token contract [ AbstractERC918.mint() ]");
453          success = mint(_nonce);
454      }
455  }
456  ```
457  
458  ### Test Cases
459  (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.)
460  
461  
462  ### Implementation
463  
464  Simple Example:
465  https://github.com/0xbitcoin/EIP918-Mineable-Token/blob/master/contracts/SimpleERC918.sol
466  
467  Complex Examples:
468  
469  https://github.com/0xbitcoin/EIP918-Mineable-Token/blob/master/contracts/0xdogeExample.sol
470  https://github.com/0xbitcoin/EIP918-Mineable-Token/blob/master/contracts/0xdogeExample2.sol
471  https://github.com/0xbitcoin/EIP918-Mineable-Token/blob/master/contracts/0xBitcoinBase.sol
472  
473  0xBitcoin Token Contract: 
474  https://etherscan.io/address/0xb6ed7644c69416d67b522e20bc294a9a9b405b31
475  
476  MVI OpenCL Token Miner 
477  https://github.com/mining-visualizer/MVis-tokenminer/releases
478  
479  PoWAdv Token Contract:
480  https://etherscan.io/address/0x1a136ae98b49b92841562b6574d1f3f5b0044e4c
481  
482  
483  ### Copyright
484  Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
485