From 530571f6106c81b2d1374a93f2f09d65ccc264e2 Mon Sep 17 00:00:00 2001 From: The MMGen Project Date: Sat, 4 Sep 2021 18:34:09 +0000 Subject: [PATCH] scripts/create-token.py: cleanups, sanity checks --- scripts/create-token.py | 77 +++++++++++++++++++++++++---------------- 1 file changed, 47 insertions(+), 30 deletions(-) diff --git a/scripts/create-token.py b/scripts/create-token.py index 3aa15539..5753105a 100755 --- a/scripts/create-token.py +++ b/scripts/create-token.py @@ -18,15 +18,17 @@ import sys,os,json,re from subprocess import run,PIPE +from collections import namedtuple from mmgen.common import * +ti = namedtuple('token_param_info',['default','conversion','test']) class TokenData: - attrs = ('decimals','supply','name','symbol','owner_addr') - decimals = 18 - supply = 10**26 - name = 'MMGen Token' - symbol = 'MMT' - owner_addr = None + fields = ('decimals','supply','name','symbol','owner_addr') + decimals = ti('18', int, lambda s: s.isdigit() and 0 < int(s) <= 36) + name = ti(None, str, lambda s: s.isascii() and s.isprintable() and len(s) < 256) + supply = ti(None, int, lambda s: s.isdigit() and 0 < int(s) <= 2**256 - 1) + symbol = ti(None, str, lambda s: s.isascii() and s.isalnum() and len(s) <= 20) + owner_addr = ti(None, str, lambda s: s.isascii() and s.isalnum() and len(s) == 40) # checked separately token_data = TokenData() @@ -39,10 +41,11 @@ opts_data = { 'options': f""" -h, --help Print this help message -o, --outdir=D Specify output directory for *.bin files --d, --decimals=D Number of decimals for the token (default: {token_data.decimals}) --n, --name=N Token name (default: {token_data.name!r}) --t, --supply=T Total supply of the token (default: {token_data.supply}) --s, --symbol=S Token symbol (default: {token_data.symbol!r}) +-d, --decimals=D Number of decimals for the token (default: {token_data.decimals.default}) +-n, --name=N Token name (REQUIRED) +-p, --preprocess Print the preprocessed code to stdout +-t, --supply=T Total supply of the token (REQUIRED) +-s, --symbol=S Token symbol (REQUIRED) -S, --stdout Output JSON data to stdout instead of files -v, --verbose Produce more verbose output -c, --check-solc-version Check the installed solc version @@ -131,12 +134,12 @@ contract Token is ERC20Interface, Owned, SafeMath { mapping(address => mapping(address => uint)) allowed; constructor() public { - symbol = ""; - name = ""; - decimals = ; - _totalSupply = ; - balances[] = _totalSupply; - emit Transfer(address(0), , _totalSupply); + symbol = "$symbol"; + name = "$name"; + decimals = $decimals; + _totalSupply = $supply; + balances[$owner_addr] = _totalSupply; + emit Transfer(address(0), $owner_addr, _totalSupply); } function totalSupply() public override returns (uint) { return _totalSupply - balances[address(0)]; @@ -172,13 +175,30 @@ contract Token is ERC20Interface, Owned, SafeMath { } """ % req_solc_ver_pat -def create_src(code,token_data,owner_addr): - token_data.owner_addr = '0x' + owner_addr - for k in token_data.attrs: - if getattr(opt,k,None): - setattr( token_data, k, getattr(opt,k) ) - code = code.replace( f'<{k.upper()}>', str(getattr(token_data,k)) ) - return code +def create_src(proto,template,token_data,owner_addr): + + def gen(): + for k in token_data.fields: + field = getattr(token_data,k) + val = ( + owner_addr if k == 'owner_addr' else + getattr(opt,k) if getattr(opt,k,None) else + field.default if field.default is not None else + die(1,f'The --{k} option must be specified') + ) + + if k == 'owner_addr': + from mmgen.obj import is_coin_addr + if not is_coin_addr( proto, owner_addr.lower() ): + die(1,f'{owner_addr}: not a valid {proto.coin} coin address') + val = '0x' + val + elif not field.test(val): + die(1,f'{val!r}: invalid parameter for option --{k}') + + yield(k,field.conversion(val)) + + from string import Template + return Template(template).substitute(**dict(gen())) def check_solc_version(): """ @@ -250,15 +270,12 @@ if __name__ == '__main__': if not len(cmd_args) == 1: opts.usage() - owner_addr = cmd_args[0] + code = create_src( proto, solidity_code_template, token_data, cmd_args[0] ) - from mmgen.obj import is_coin_addr - if not is_coin_addr( proto, owner_addr.lower() ): - die(1,f'{owner_addr}: not a valid {proto.coin} coin address') + if opt.preprocess: + Die(0,code) - out = compile_code( - create_src( solidity_code_template, token_data, owner_addr ) - ) + out = compile_code(code) if opt.stdout: print(json.dumps(out))