create-token.py 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. #!/usr/bin/env python3
  2. #
  3. # mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
  4. # Copyright (C)2013-2018 The MMGen Project <mmgen@tuta.io>
  5. #
  6. # This program is free software: you can redistribute it and/or modify
  7. # it under the terms of the GNU General Public License as published by
  8. # the Free Software Foundation, either version 3 of the License, or
  9. # (at your option) any later version.
  10. #
  11. # This program is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. # GNU General Public License for more details.
  15. #
  16. # You should have received a copy of the GNU General Public License
  17. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. import sys,os,json
  19. from subprocess import Popen,PIPE
  20. from mmgen.common import *
  21. from mmgen.obj import CoinAddr,is_coin_addr
  22. decimals = 18
  23. supply = 10**26
  24. name = 'MMGen Token'
  25. symbol = 'MMT'
  26. opts_data = lambda: {
  27. 'desc': 'Create an ERC20 token contract',
  28. 'usage':'[opts] <owner address>',
  29. 'options': """
  30. -h, --help Print this help message
  31. -o, --outdir= d Specify output directory for *.bin files
  32. -d, --decimals=d Number of decimals for the token (default: {d})
  33. -n, --name=n Token name (default: {n})
  34. -t, --supply= t Total supply of the token (default: {t})
  35. -s, --symbol= s Token symbol (default: {s})
  36. -S, --stdout Output data in JSON format to stdout instead of files
  37. """.format(d=decimals,n=name,s=symbol,t=supply)
  38. }
  39. cmd_args = opts.init(opts_data)
  40. assert g.coin in ('ETH','ETC'),'--coin option must be set to ETH or ETC'
  41. if not len(cmd_args) == 1 or not is_coin_addr(cmd_args[0]):
  42. opts.usage()
  43. owner_addr = '0x' + CoinAddr(cmd_args[0])
  44. # ERC Token Standard #20 Interface
  45. # https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md
  46. code_in = """
  47. pragma solidity ^0.4.18;
  48. contract SafeMath {
  49. function safeAdd(uint a, uint b) public pure returns (uint c) {
  50. c = a + b;
  51. require(c >= a);
  52. }
  53. function safeSub(uint a, uint b) public pure returns (uint c) {
  54. require(b <= a);
  55. c = a - b;
  56. }
  57. function safeMul(uint a, uint b) public pure returns (uint c) {
  58. c = a * b;
  59. require(a == 0 || c / a == b);
  60. }
  61. function safeDiv(uint a, uint b) public pure returns (uint c) {
  62. require(b > 0);
  63. c = a / b;
  64. }
  65. }
  66. contract ERC20Interface {
  67. function totalSupply() public constant returns (uint);
  68. function balanceOf(address tokenOwner) public constant returns (uint balance);
  69. function allowance(address tokenOwner, address spender) public constant returns (uint remaining);
  70. function transfer(address to, uint tokens) public returns (bool success);
  71. function approve(address spender, uint tokens) public returns (bool success);
  72. function transferFrom(address from, address to, uint tokens) public returns (bool success);
  73. event Transfer(address indexed from, address indexed to, uint tokens);
  74. event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
  75. }
  76. // Contract function to receive approval and execute function in one call
  77. contract ApproveAndCallFallBack {
  78. function receiveApproval(address from, uint256 tokens, address token, bytes data) public;
  79. }
  80. contract Owned {
  81. address public owner;
  82. address public newOwner;
  83. event OwnershipTransferred(address indexed _from, address indexed _to);
  84. constructor() public {
  85. owner = msg.sender;
  86. }
  87. modifier onlyOwner {
  88. require(msg.sender == owner);
  89. _;
  90. }
  91. function transferOwnership(address _newOwner) public onlyOwner {
  92. newOwner = _newOwner;
  93. }
  94. function acceptOwnership() public {
  95. require(msg.sender == newOwner);
  96. emit OwnershipTransferred(owner, newOwner);
  97. owner = newOwner;
  98. newOwner = address(0);
  99. }
  100. }
  101. // ----------------------------------------------------------------------------
  102. // ERC20 Token, with the addition of symbol, name and decimals and assisted
  103. // token transfers
  104. // ----------------------------------------------------------------------------
  105. contract Token is ERC20Interface, Owned, SafeMath {
  106. string public symbol;
  107. string public name;
  108. uint8 public decimals;
  109. uint public _totalSupply;
  110. mapping(address => uint) balances;
  111. mapping(address => mapping(address => uint)) allowed;
  112. constructor() public {
  113. symbol = "<SYMBOL>";
  114. name = "<NAME>";
  115. decimals = <DECIMALS>;
  116. _totalSupply = <SUPPLY>;
  117. balances[<OWNER_ADDR>] = _totalSupply;
  118. emit Transfer(address(0), <OWNER_ADDR>, _totalSupply);
  119. }
  120. function totalSupply() public constant returns (uint) {
  121. return _totalSupply - balances[address(0)];
  122. }
  123. function balanceOf(address tokenOwner) public constant returns (uint balance) {
  124. return balances[tokenOwner];
  125. }
  126. function transfer(address to, uint tokens) public returns (bool success) {
  127. balances[msg.sender] = safeSub(balances[msg.sender], tokens);
  128. balances[to] = safeAdd(balances[to], tokens);
  129. emit Transfer(msg.sender, to, tokens);
  130. return true;
  131. }
  132. function approve(address spender, uint tokens) public returns (bool success) {
  133. allowed[msg.sender][spender] = tokens;
  134. emit Approval(msg.sender, spender, tokens);
  135. return true;
  136. }
  137. function transferFrom(address from, address to, uint tokens) public returns (bool success) {
  138. balances[from] = safeSub(balances[from], tokens);
  139. allowed[from][msg.sender] = safeSub(allowed[from][msg.sender], tokens);
  140. balances[to] = safeAdd(balances[to], tokens);
  141. emit Transfer(from, to, tokens);
  142. return true;
  143. }
  144. function allowance(address tokenOwner, address spender) public constant returns (uint remaining) {
  145. return allowed[tokenOwner][spender];
  146. }
  147. function approveAndCall(address spender, uint tokens, bytes data) public returns (bool success) {
  148. allowed[msg.sender][spender] = tokens;
  149. emit Approval(msg.sender, spender, tokens);
  150. ApproveAndCallFallBack(spender).receiveApproval(msg.sender, tokens, this, data);
  151. return true;
  152. }
  153. // Don't accept ETH
  154. function () public payable {
  155. revert();
  156. }
  157. // Owner can transfer out any accidentally sent ERC20 tokens
  158. function transferAnyERC20Token(address tokenAddress, uint tokens) public onlyOwner returns (bool success) {
  159. return ERC20Interface(tokenAddress).transfer(owner, tokens);
  160. }
  161. }
  162. """
  163. def create_src(code):
  164. for k in ('decimals','supply','name','symbol','owner_addr'):
  165. if hasattr(opt,k) and getattr(opt,k): globals()[k] = getattr(opt,k)
  166. code = code.replace('<{}>'.format(k.upper()),str(globals()[k]))
  167. return code
  168. def compile_code(code):
  169. cmd = ['solc','--optimize','--bin','--overwrite']
  170. if not opt.stdout: cmd += ['--output-dir', opt.outdir or '.']
  171. p = Popen(cmd,stdin=PIPE,stdout=PIPE,stderr=PIPE)
  172. res = p.communicate(code.encode())
  173. o = res[0].decode().replace('\r','').split('\n')
  174. dmsg(res[1])
  175. if opt.stdout:
  176. return dict((k,o[i+2]) for k in ('SafeMath','Owned','Token') for i in range(len(o)) if k in o[i])
  177. src = create_src(code_in)
  178. out = compile_code(src)
  179. if opt.stdout:
  180. print(json.dumps(out))