create-token.py 6.4 KB

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