# standard imports import logging import os # external imports from eth_accounts_index import AccountsIndex from erc20_faucet import Faucet from cic_contracts.erc20 import ERC20 from chainlib.eth.error import RequestMismatchException from chainlib.eth.address import AddressChecksum from chainlib.eth.constant import ZERO_ADDRESS from hexathon import uniform, add_0x logg = logging.getLogger(__name__) faucet_token_cache = {} token_cache = {} def get_method(chain_str, tx): data = tx.payload s = None if len(data) < 8: raise ValueError('not minimum signature length') data = uniform(data[:8]) chainmap = addrmap.get(chain_str) if chainmap != None: contractmap = chainmap.get(uniform(tx.inputs[0])) if contractmap != None: m = contractmap.get(data) if m != None: return m chainmap = sigmap.get(chain_str) if chainmap != None: return chainmap.get(data) def apply(c, s, chain_spec, conn, block, tx, db_session=None): try: m = get_method(str(chain_spec), tx) except ValueError as e: return s if m == None: return s r = m(c, s, chain_spec, conn, block, tx) if r != None: s = r return s def account_registry_add(c, s, chain_spec, conn, block, tx): try: o = AccountsIndex.parse_add_request(tx.payload) s = '{} block {} tx {} account registration for {}'.format(c, block.number, tx.index, o[0]) return s except RequestMismatchException as e: pass return None def ge_faucet_gift(i, s, chain_spec, conn, block, tx): c = Faucet(chain_spec) o = c.token_amount(tx.inputs[0], sender_address=ZERO_ADDRESS, height=block.number) r = conn.do(o) v = c.parse_token_amount(r) logg.info('retrieved token amount {} at block height {} for faucet {}'.format(v, block.number, tx.inputs[0])) token = faucet_token_cache.get(tx.inputs[0]) if token == None: o = c.token(tx.inputs[0], sender_address=ZERO_ADDRESS) r = conn.do(o) token = c.parse_token(r) token = uniform(token) faucet_token_cache[tx.inputs[0]] = token logg.info('found token {} for faucet {}'.format(v, token, tx.inputs[0])) token_symbol = token_cache.get(token) if token_symbol == None: c = ERC20(chain_spec) o = c.symbol(token, sender_address=ZERO_ADDRESS) r = conn.do(o) token_symbol = c.parse_symbol(r) token_cache[token] = token_symbol logg.info('resolved token {} to symbol'.format(v, block.number, tx.inputs[0])) try: o = Faucet.parse_give_to_request(tx.payload) s = '{} GE faucet was triggered for {} {} by {} on block {} tx {}'.format(i, v, token_symbol, o[0], block.number, tx.index) return s except RequestMismatchException as e: pass return None def erc20_transfer(c, s, chain_spec, conn, block, tx): t = ERC20(chain_spec) try: transfer_data = t.parse_transfer_request(tx.payload) token_sender = tx.outputs[0] token_recipient = transfer_data[0] token_value = transfer_data[1] return '{} GFT {} sent from {} to {}'.format(c, token_value ,add_0x(token_sender), add_0x(token_recipient)) except RequestMismatchException as e: pass return None sigmap = { 'evm:byzantium:8996:bloxberg': { '0a3b0a4f': account_registry_add, }, } addrmap = { 'evm:byzantium:8996:bloxberg': { 'd462aadb7251d418e6a9e4f205928f678e1c6b3b': { '63e4bff4': ge_faucet_gift, }, '32e860c2a0645d1b7b005273696905f5d6dc5d05': { 'a9059cbb': erc20_transfer, }, }, }