def wait_for_transaction_receipt(transaction_hash: str, timeout: int = config["timeout"], network: str = config["network"], provider: str = config["provider"], token: Optional[str] = None) -> dict: """ Wait for Ethereum transaction receipt. :param transaction_hash: Ethereum transaction hash/id. :type transaction_hash: str :param timeout: Request timeout, default to 60. :type timeout: int :param network: Ethereum network, defaults to ``mainnet``. :type network: str :param provider: Ethereum network provider, defaults to ``http``. :type provider: str :param token: Infura API endpoint token, defaults to ``4414fea5f7454211956b1627621450b4``. :type token: str :returns: dict -- Ethereum transaction receipt. >>> from swap.providers.ethereum.rpc import wait_for_transaction_receipt >>> wait_for_transaction_receipt(transaction_hash="d26220f61ff4207837ee3cf5ab2a551b2476389ae76cf1ccd2005d304bdc308d", timeout=120, network="testnet") {'transactionHash': '0xd26220f61ff4207837ee3cf5ab2a551b2476389ae76cf1ccd2005d304bdc308d', 'transactionIndex': 0, 'blockHash': '0xb325934bfb333b5ca77634081cfeaedfa53598771dcfcb482ed3ace789ec5843', 'blockNumber': 1, 'from': '0x69e04fe16c9A6A83076B3c2dc4b4Bc21b5d9A20C', 'to': None, 'gasUsed': 1582730, 'cumulativeGasUsed': 1582730, 'contractAddress': '0xeaEaC81da5E386E8Ca4De1e64d40a10E468A5b40', 'logs': [], 'status': 1, 'logsBloom': '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'} """ web3: Web3 = get_web3(network=network, provider=provider, token=token) transaction_dict: dict = web3.eth.wait_for_transaction_receipt( transaction_hash=HexBytes(transaction_hash), timeout=timeout).__dict__ for key, value in transaction_dict.items(): if isinstance(value, HexBytes): transaction_dict[key] = transaction_dict[key].hex() return transaction_dict
def sign_message(self, account: str, message: bytes, content_type: str = None, validator_address: str = None, **kwargs) -> HexBytes: """ See https://github.com/ethereum/go-ethereum/blob/a32a2b933ad6793a2fe4172cd46c5c5906da259a/signer/core/signed_data.go#L185 """ if isinstance(message, bytes): message = Web3.toHex(message) if not content_type: content_type = self.DEFAULT_CONTENT_TYPE elif content_type not in self.SIGN_DATA_CONTENT_TYPES: raise ValueError(f'{content_type} is not a valid content type. ' f'Valid types are {self.SIGN_DATA_CONTENT_TYPES}') if content_type == self.SIGN_DATA_FOR_VALIDATOR: if not validator_address or validator_address == NULL_ADDRESS: raise ValueError( 'When using the intended validator type, a validator address is required.' ) data = {'address': validator_address, 'message': message} elif content_type == self.SIGN_DATA_FOR_ECRECOVER: data = message else: raise NotImplementedError signed_data = self.__ipc_request("account_signData", content_type, account, data) return HexBytes(signed_data)
def str_attribute(data: str) -> Union[HexBytes, str]: if is_address(data): return to_checksum_address(data, prefix="0x") elif data.startswith("0x"): return HexBytes(data) else: return data
def test_code_exists(mocker): w3_mock = mocker.MagicMock() w3_mock.eth.getCode.return_value = 0 address = '0x123' assert not code_exists(w3_mock, address) w3_mock.eth.getCode.return_value = HexBytes('') assert not code_exists(w3_mock, address) w3_mock.eth.getCode.return_value = HexBytes('0x') assert not code_exists(w3_mock, address) w3_mock.eth.getCode.return_value = HexBytes('0x0') assert not code_exists(w3_mock, address) w3_mock.eth.getCode.return_value = HexBytes('0x00') assert not code_exists(w3_mock, address) w3_mock.eth.getCode.return_value = HexBytes(address) assert code_exists(w3_mock, address)
async def call_contract_method(self, method, to_int=False, to_string=False): contract_address = self.get_contract_addr() result = await self.post('eth_call', { 'to': contract_address, 'data': self.get_method_hash(method) }, 'latest') if to_int: return int(result, 16) elif to_string: return decode_abi(['string'], HexBytes(result))[0].decode() return result
def test_events_logs(self): contract_abi = [self.log_bet_abi] with patch_get_abi(json.dumps(contract_abi)): etheroll = Etheroll() event_list = ("LogBet", ) expected_events_logs = [{ "address": "0xA52e014B3f5Cc48287c2D483A3E026C32cc76E6d", "blockHash": HexBytes("0x" "ccab3e5d9a4ae42331532a12618be5cb" "682259c46b7c068db96d854a4b49cbc4"), "blockNumber": 8651490, "data": ("0x" "00000000000000000000000000000000" "00000000000000000007401c9431d633" "00000000000000000000000000000000" "000000000000000002c68af0bb140000" "00000000000000000000000000000000" "00000000000000000000000000000063" "00000000000000000000000000000000" "0000000000000000000000000004b8e0"), "logIndex": 90, "removed": False, "topics": [ HexBytes("0x" "56b3f1a6cd856076d6f8adbf8170c43a" "0b0f532fc5696a2699a0e0cabc704163"), HexBytes("0x" "5b7f3ee4074f2a1e3b863607f7edd722" "0bbb15cbf43543e813fa5a88683d4ebe"), HexBytes("0x" "000000000000000000000000bfcd44f5" "1a93bebf90cb6048d593542c572c1693"), HexBytes("0x" "00000000000000000000000000000000" "000000000000000002cdcb0d4f45d633"), ], "transactionHash": HexBytes("0x" "db189e74bb2055748686bb1a1099dcc6" "51d97b21530debbd7258dcfd55dc95f0"), "transactionIndex": 115, "transactionLogIndex": "0x1", "type": "mined", }] with mock.patch("web3.eth.Eth.filter") as m_filter: m_filter().get_all_entries.return_value = expected_events_logs events_logs = etheroll.events_logs(event_list) assert events_logs == expected_events_logs
def sign_transaction(self, transaction_dict: dict) -> HexBytes: formatters = { 'nonce': Web3.toHex, 'gasPrice': Web3.toHex, 'gas': Web3.toHex, 'value': Web3.toHex, 'chainId': Web3.toHex, 'from': to_checksum_address } # Workaround for contract creation TXs if transaction_dict['to'] == b'': transaction_dict['to'] = None elif transaction_dict['to']: formatters['to'] = to_checksum_address formatted_transaction = apply_formatters_to_dict( formatters, transaction_dict) signed = self.__ipc_request("account_signTransaction", formatted_transaction) return HexBytes(signed.raw)
def get_bets_logs(self, address, from_block, to_block="latest"): """ Retrieves `address` last bets from event logs and returns the list of bets with decoded info. Does not return the actual roll result. Least recent first (index 0), most recent last (index -1). """ bets = () bet_events = self.get_log_bet_events(address, from_block, to_block) transaction_debugger = TransactionDebugger(self.contract_abi) for bet_event in bet_events: topics = [HexBytes(topic) for topic in bet_event["topics"]] log_data = bet_event["data"] decoded_method = transaction_debugger.decode_method( topics, log_data ) call = decoded_method["call"] bet_id = call["BetID"].hex() reward_value = call["RewardValue"] reward_value_ether = round(reward_value / 1e18, ROUND_DIGITS) profit_value = call["ProfitValue"] profit_value_ether = round(profit_value / 1e18, ROUND_DIGITS) bet_value = call["BetValue"] bet_value_ether = round(bet_value / 1e18, ROUND_DIGITS) roll_under = call["PlayerNumber"] timestamp = bet_event["timeStamp"] date_time = timestamp2datetime(timestamp) transaction_hash = bet_event["transactionHash"] bet = { "bet_id": bet_id, "reward_value_ether": reward_value_ether, "profit_value_ether": profit_value_ether, "bet_value_ether": bet_value_ether, "roll_under": roll_under, "timestamp": timestamp, "datetime": date_time, "transaction_hash": transaction_hash, } bets += (bet,) return bets
def get_bets_logs(self, address, from_block, to_block='latest'): """ Retrieves `address` last bets from event logs and returns the list of bets with decoded info. Does not return the actual roll result. Least recent first (index 0), most recent last (index -1). """ bets = [] bet_events = self.get_log_bet_events(address, from_block, to_block) transaction_debugger = TransactionDebugger(self.contract_abi) for bet_event in bet_events: topics = [HexBytes(topic) for topic in bet_event['topics']] log_data = bet_event['data'] decoded_method = transaction_debugger.decode_method( topics, log_data) call = decoded_method['call'] bet_id = call['BetID'].hex() reward_value = call['RewardValue'] reward_value_ether = round(reward_value / 1e18, ROUND_DIGITS) profit_value = call['ProfitValue'] profit_value_ether = round(profit_value / 1e18, ROUND_DIGITS) bet_value = call['BetValue'] bet_value_ether = round(bet_value / 1e18, ROUND_DIGITS) roll_under = call['PlayerNumber'] timestamp = bet_event['timeStamp'] date_time = datetime.utcfromtimestamp(int(timestamp, 16)) transaction_hash = bet_event['transactionHash'] bet = { 'bet_id': bet_id, 'reward_value_ether': reward_value_ether, 'profit_value_ether': profit_value_ether, 'bet_value_ether': bet_value_ether, 'roll_under': roll_under, 'timestamp': timestamp, 'datetime': date_time, 'transaction_hash': transaction_hash, } bets.append(bet) return bets
def get_bet_results_logs(self, address, from_block, to_block="latest"): """ Retrieves `address` bet results from event logs and returns the list of bet results with decoded info. """ results = () result_events = self.get_log_result_events( address, from_block, to_block ) transaction_debugger = TransactionDebugger(self.contract_abi) for result_event in result_events: topics = [HexBytes(topic) for topic in result_event["topics"]] log_data = result_event["data"] decoded_method = transaction_debugger.decode_method( topics, log_data ) call = decoded_method["call"] bet_id = call["BetID"].hex() roll_under = call["PlayerNumber"] dice_result = call["DiceResult"] # not to be mistaken with what the user bet here, in this case it's # what he will receive/loss as a result of his bet bet_value = call["Value"] bet_value_ether = round(bet_value / 1e18, ROUND_DIGITS) timestamp = result_event["timeStamp"] date_time = timestamp2datetime(timestamp) transaction_hash = result_event["transactionHash"] bet = { "bet_id": bet_id, "roll_under": roll_under, "dice_result": dice_result, "bet_value_ether": bet_value_ether, "timestamp": timestamp, "datetime": date_time, "transaction_hash": transaction_hash, } results += (bet,) return results
def __init__(self, contractList, network, tx_hash): compiled_sol = os.path.join( './build', contractList['SmartCheck'][2:].replace('.sol', '.json')) with open(compiled_sol, 'r') as f: contract_interface = json.load(f) # web3.py instance w3 = Web3(Web3.HTTPProvider(network)) # Get tx receipt to get contract address tx_Hash = HexBytes(tx_hash) tx_receipt = w3.eth.getTransactionReceipt(tx_Hash) contract_address = tx_receipt['contractAddress'] # Contract instance in concise mode abi = contract_interface['abi'] contract_instance = w3.eth.contract( address=contract_address, abi=abi, ContractFactoryClass=ConciseContract) self.w3 = w3 self.contract_instance = contract_instance
def get_bet_results_logs(self, address, from_block, to_block='latest'): """ Retrieves `address` bet results from event logs and returns the list of bet results with decoded info. """ results = [] result_events = self.get_log_result_events(address, from_block, to_block) transaction_debugger = TransactionDebugger(self.contract_abi) for result_event in result_events: topics = [HexBytes(topic) for topic in result_event['topics']] log_data = result_event['data'] decoded_method = transaction_debugger.decode_method( topics, log_data) call = decoded_method['call'] bet_id = call['BetID'].hex() roll_under = call['PlayerNumber'] dice_result = call['DiceResult'] # not to be mistaken with what the user bet here, in this case it's # what he will receive/loss as a result of his bet bet_value = call['Value'] bet_value_ether = round(bet_value / 1e18, ROUND_DIGITS) timestamp = result_event['timeStamp'] date_time = datetime.utcfromtimestamp(int(timestamp, 16)) transaction_hash = result_event['transactionHash'] bet = { 'bet_id': bet_id, 'roll_under': roll_under, 'dice_result': dice_result, 'bet_value_ether': bet_value_ether, 'timestamp': timestamp, 'datetime': date_time, 'transaction_hash': transaction_hash, } results.append(bet) return results
def test_decode_method_log1(self): """Trying to decode a `Log1()` event call.""" # simplified contract ABI for tests contract_abi = [ {"inputs": [], "type": "constructor", "payable": False}, {"payable": False, "type": "fallback"}, { "inputs": [ {"indexed": False, "type": "address", "name": "sender"}, {"indexed": False, "type": "bytes32", "name": "cid"}, {"indexed": False, "type": "uint256", "name": "timestamp"}, {"indexed": False, "type": "string", "name": "datasource"}, {"indexed": False, "type": "string", "name": "arg"}, {"indexed": False, "type": "uint256", "name": "gaslimit"}, {"indexed": False, "type": "bytes1", "name": "proofType"}, {"indexed": False, "type": "uint256", "name": "gasPrice"}, ], "type": "event", "name": "Log1", "anonymous": False, }, { "inputs": [ {"indexed": False, "type": "address", "name": "sender"}, {"indexed": False, "type": "bytes32", "name": "cid"}, {"indexed": False, "type": "uint256", "name": "timestamp"}, {"indexed": False, "type": "string", "name": "datasource"}, {"indexed": False, "type": "string", "name": "arg1"}, {"indexed": False, "type": "string", "name": "arg2"}, {"indexed": False, "type": "uint256", "name": "gaslimit"}, {"indexed": False, "type": "bytes1", "name": "proofType"}, {"indexed": False, "type": "uint256", "name": "gasPrice"}, ], "type": "event", "name": "Log2", "anonymous": False, }, { "inputs": [ {"indexed": False, "type": "address", "name": "sender"}, {"indexed": False, "type": "bytes32", "name": "cid"}, {"indexed": False, "type": "uint256", "name": "timestamp"}, {"indexed": False, "type": "string", "name": "datasource"}, {"indexed": False, "type": "bytes", "name": "args"}, {"indexed": False, "type": "uint256", "name": "gaslimit"}, {"indexed": False, "type": "bytes1", "name": "proofType"}, {"indexed": False, "type": "uint256", "name": "gasPrice"}, ], "type": "event", "name": "LogN", "anonymous": False, }, ] topics = [ HexBytes( "b76d0edd90c6a07aa3ff7a222d7f5933" "e29c6acc660c059c97837f05c4ca1a84" ) ] log_data = ( "0x" "000000000000000000000000fe8a5f3a7bb446e1cb4566717691cd3139289ed4" "b0230ab70b78e47050766089ea333f2ff7ad41c6f31e8bed8c2acfcb8e911841" "0000000000000000000000000000000000000000000000000000000000000000" "0000000000000000000000000000000000000000000000000000000000000100" "0000000000000000000000000000000000000000000000000000000000000140" "00000000000000000000000000000000000000000000000000000000000395f8" "1100000000000000000000000000000000000000000000000000000000000000" "00000000000000000000000000000000000000000000000000000004a817c800" "0000000000000000000000000000000000000000000000000000000000000006" "6e65737465640000000000000000000000000000000000000000000000000000" "00000000000000000000000000000000000000000000000000000000000001b4" "5b55524c5d205b276a736f6e2868747470733a2f2f6170692e72616e646f6d2e" "6f72672f6a736f6e2d7270632f312f696e766f6b65292e726573756c742e7261" "6e646f6d5b2273657269616c4e756d626572222c2264617461225d272c20275c" "6e7b226a736f6e727063223a22322e30222c226d6574686f64223a2267656e65" "726174655369676e6564496e746567657273222c22706172616d73223a7b2261" "70694b6579223a247b5b646563727970745d20424b6733544373376c6b7a4e72" "316b523670786a50434d32534f656a63466f6a55504d544f73426b432f343748" "485066317350326f78564c546a4e42752b736c523953675a797144746a564f56" "35597a67313269556b62756270304470636a434564654a54486e477743366744" "3732394755566f47766f393668757877526f5a6c436a594f3830725771325747" "596f522f4c433357616d704475767632426f3d7d2c226e223a312c226d696e22" "3a312c226d6178223a3130302c227265706c6163656d656e74223a747275652c" "2262617365223a3130247b5b6964656e746974795d20227d227d2c226964223a" "31247b5b6964656e746974795d20227d227d275d000000000000000000000000" ) transaction_debugger = TransactionDebugger(contract_abi) decoded_method = transaction_debugger.decode_method(topics, log_data) # TODO: simplify that arg call for unit testing assert decoded_method["call"] == { "arg": ( "[URL] ['json(https://api.random.org/json-rpc/1/invoke).resul" 't.random["serialNumber","data"]\', \'\\n{"jsonrpc":"2.0","met' 'hod":"generateSignedIntegers","params":{"apiKey":${[decrypt] ' "BKg3TCs7lkzNr1kR6pxjPCM2SOejcFojUPMTOsBkC/47HHPf1sP2oxVLTjNBu" "+slR9SgZyqDtjVOV5Yzg12iUkbubp0DpcjCEdeJTHnGwC6gD729GUVoGvo96h" 'uxwRoZlCjYO80rWq2WGYoR/LC3WampDuvv2Bo=},"n":1,"min":1,"max":1' '00,"replacement":true,"base":10${[identity] "}"},"id":1${[ide' 'ntity] "}"}\']' ), "cid": ( b"\xb0#\n\xb7\x0bx\xe4pPv`\x89\xea3?/\xf7\xadA\xc6\xf3\x1e" b"\x8b\xed\x8c*\xcf\xcb\x8e\x91\x18A" ), "datasource": "nested", "gasPrice": 20000000000, "gaslimit": 235000, "proofType": b"\x11", "sender": "0xfe8a5f3a7bb446e1cb4566717691cd3139289ed4", "timestamp": 0, } assert decoded_method["method_info"]["definition"] == ( "Log1(" "address,bytes32,uint256,string,string,uint256,bytes1,uint256)" ) assert decoded_method["method_info"]["sha3"].hex() == ( "0x" "b76d0edd90c6a07aa3ff7a222d7f5933" "e29c6acc660c059c97837f05c4ca1a84" )
def test_decode_method_log_bet(self): """Trying to decode a `LogBet()` event call.""" # simplified contract ABI contract_abi = [ { "inputs": [ {"type": "uint256", "name": "newMaxProfitAsPercent"} ], "constant": False, "name": "ownerSetMaxProfitAsPercentOfHouse", "outputs": [], "stateMutability": "nonpayable", "payable": False, "type": "function", }, { "inputs": [], "constant": True, "name": "treasury", "outputs": [{"type": "address", "name": ""}], "stateMutability": "view", "payable": False, "type": "function", }, { "inputs": [], "constant": True, "name": "totalWeiWagered", "outputs": [{"type": "uint256", "name": ""}], "stateMutability": "view", "payable": False, "type": "function", }, { "inputs": [{"type": "uint256", "name": "newMinimumBet"}], "constant": False, "name": "ownerSetMinBet", "outputs": [], "stateMutability": "nonpayable", "payable": False, "type": "function", }, { "stateMutability": "nonpayable", "inputs": [], "type": "constructor", "payable": False, }, { "stateMutability": "payable", "payable": True, "type": "fallback", }, { "inputs": [ {"indexed": True, "type": "bytes32", "name": "BetID"}, { "indexed": True, "type": "address", "name": "PlayerAddress", }, { "indexed": True, "type": "uint256", "name": "RewardValue", }, { "indexed": False, "type": "uint256", "name": "ProfitValue", }, {"indexed": False, "type": "uint256", "name": "BetValue"}, { "indexed": False, "type": "uint256", "name": "PlayerNumber", }, ], "type": "event", "name": "LogBet", "anonymous": False, }, ] topics = [ HexBytes( "1cb5bfc4e69cbacf65c8e05bdb84d7a3" "27bd6bb4c034ff82359aefd7443775c4" ), HexBytes( "b0230ab70b78e47050766089ea333f2f" "f7ad41c6f31e8bed8c2acfcb8e911841" ), HexBytes( "00000000000000000000000066d4bacf" "e61df23be813089a7a6d1a749a5c936a" ), HexBytes( "00000000000000000000000000000000" "0000000000000000016a98b78c556c34" ), ] log_data = ( "0x" "0000000000000000000000000000000000000000000000000007533f2ecb6c34" "000000000000000000000000000000000000000000000000016345785d8a0000" "0000000000000000000000000000000000000000000000000000000000000062" ) transaction_debugger = TransactionDebugger(contract_abi) decoded_method = transaction_debugger.decode_method(topics, log_data) assert decoded_method["call"] == { "BetID": ( b"\xb0#\n\xb7\x0bx\xe4pPv`\x89\xea3?/\xf7\xadA\xc6\xf3\x1e\x8b" b"\xed\x8c*\xcf\xcb\x8e\x91\x18A" ), "BetValue": 100000000000000000, "PlayerAddress": "0x66d4bacfe61df23be813089a7a6d1a749a5c936a", "PlayerNumber": 98, "ProfitValue": 2061855670103092, "RewardValue": 102061855670103092, } assert decoded_method["method_info"]["definition"] == ( "LogBet(bytes32,address,uint256,uint256,uint256,uint256)" ) assert decoded_method["method_info"]["sha3"].hex() == ( "0x" "1cb5bfc4e69cbacf65c8e05bdb84d7a3" "27bd6bb4c034ff82359aefd7443775c4" )
from hexbytes.main import HexBytes from web3.utils.datastructures import AttributeDict eth_initial_transaction = AttributeDict({ 'blockHash': HexBytes('0xebb8d4e62dc5b0732bee6e2c3946c5a972988f41fbac321eb73311930a936804'), 'blockNumber': 6600435, 'chainId': None, 'condition': None, 'creates': None, 'from': '0x999F348959E611F1E9eab2927c21E88E48e6Ef45', 'gas': 126221, 'gasPrice': 14959965017, 'hash': HexBytes('0x7221773115ded91f856cedb2032a529edabe0bab8785d07d901681512314ef41'), 'input': ( '0xeb8ae1ed000000000000000000000000000000000000000000000000000000005abe25ea10ff9' '72f3d8181f603aa7f6b4bc172de730fec2b00000000000000000000000000000000000000000000' '0000d867f293ba129629a9f9355fa285b8d3711a9092' ), 'nonce': 16, 'publicKey': HexBytes( '0x76c4f5810736d1d9b9964863abc339dce70ace058db5c820e5fdec26e0840f36f9adcb150e521' '6213bc301f3a6b71a178c81ddd34a361d696c8cb03970590d4f' ), 'r': HexBytes('0x7a4e11ea96640fb0ab255960cea6afcf16732246ce1dadeec52eb6a8d59c2e05'), 'raw': HexBytes( '0xf8ca1085037baef3598301ed0d949f7e5402ed0858ea0c5914d44b900a42c89547b80cb864eb8' 'ae1ed000000000000000000000000000000000000000000000000000000005abe25ea10ff972f3d' '8181f603aa7f6b4bc172de730fec2b000000000000000000000000000000000000000000000000d' '867f293ba129629a9f9355fa285b8d3711a90921ba07a4e11ea96640fb0ab255960cea6afcf1673' '2246ce1dadeec52eb6a8d59c2e05a06f47ffe2bc88915013295be61c503bc52762fe4f7826fa249' '0b2d302a11bff85'
from hexbytes.main import HexBytes from web3.utils.datastructures import AttributeDict eth_initial_transaction = AttributeDict({ 'blockHash': HexBytes( '0x111346453964a0df4fcd50ac759231f4f90a858c6ab62255e7c75089b22b0b40'), 'blockNumber': 8388823, 'chainId': None, 'condition': None, 'creates': None, 'from': '0x999F348959E611F1E9eab2927c21E88E48e6Ef45', 'gas': 140502, 'gasPrice': 1000000000, 'hash': HexBytes( '0xcf64ef4d0449cf7a78d2be1c1f7225dffb11dded98a58d569ebcc6e883ce9f2b'), 'input': '0x7337c993000000000000000000000000000000000000000000000000000000005b782cfaed2e6fe492005de2dd82e84d38448' '467d632e81c000000000000000000000000000000000000000000000000d867f293ba129629a9f9355fa285b8d3711a90920000' '0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' '0000000000000000000000000000000000000000000000000000000000000000000000000000000000000', 'nonce': 283,
def sign_message(self, account: str, message: bytes, **kwargs) -> HexBytes: signer = self.__get_signer(account=account) signature = signer.sign_message(signable_message=encode_defunct( primitive=message)).signature return HexBytes(signature)
def test_decode_transaction_logs(self): """ Mocking `web3.eth.Eth.getTransactionReceipt()` response and verifies decoding transaction works as expected. """ mocked_logs = [ AttributeDict( { "address": "0xCBf1735Aad8C4B337903cD44b419eFE6538aaB40", "topics": [ HexBytes( "b76d0edd90c6a07aa3ff7a222d7f5933" "e29c6acc660c059c97837f05c4ca1a84" ) ], "data": ( "000000000000000000000000fe8a5f3a" "7bb446e1cb4566717691cd3139289ed4" "b0230ab70b78e47050766089ea333f2f" "f7ad41c6f31e8bed8c2acfcb8e911841" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000100" "00000000000000000000000000000000" "00000000000000000000000000000140" "00000000000000000000000000000000" "000000000000000000000000000395f8" "11000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "000000000000000000000004a817c800" "00000000000000000000000000000000" "00000000000000000000000000000006" "6e657374656400000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "000000000000000000000000000001b4" "5b55524c5d205b276a736f6e28687474" "70733a2f2f6170692e72616e646f6d2e" "6f72672f6a736f6e2d7270632f312f69" "6e766f6b65292e726573756c742e7261" "6e646f6d5b2273657269616c4e756d62" "6572222c2264617461225d272c20275c" "6e7b226a736f6e727063223a22322e30" "222c226d6574686f64223a2267656e65" "726174655369676e6564496e74656765" "7273222c22706172616d73223a7b2261" "70694b6579223a247b5b646563727970" "745d20424b6733544373376c6b7a4e72" "316b523670786a50434d32534f656a63" "466f6a55504d544f73426b432f343748" "485066317350326f78564c546a4e4275" "2b736c523953675a797144746a564f56" "35597a67313269556b62756270304470" "636a434564654a54486e477743366744" "3732394755566f47766f393668757877" "526f5a6c436a594f3830725771325747" "596f522f4c433357616d704475767632" "426f3d7d2c226e223a312c226d696e22" "3a312c226d6178223a3130302c227265" "706c6163656d656e74223a747275652c" "2262617365223a3130247b5b6964656e" "746974795d20227d227d2c226964223a" "31247b5b6964656e746974795d20227d" "227d275d000000000000000000000000" ), } ), AttributeDict( { "address": "0xFE8a5f3a7Bb446e1cB4566717691cD3139289ED4", "topics": [ HexBytes( "1cb5bfc4e69cbacf65c8e05bdb84d7a3" "27bd6bb4c034ff82359aefd7443775c4" ), HexBytes( "b0230ab70b78e47050766089ea333f2f" "f7ad41c6f31e8bed8c2acfcb8e911841" ), HexBytes( "00000000000000000000000066d4bacf" "e61df23be813089a7a6d1a749a5c936a" ), HexBytes( "00000000000000000000000000000000" "0000000000000000016a98b78c556c34" ), ], "data": ( "00000000000000000000000000000000" "00000000000000000007533f2ecb6c34" "00000000000000000000000000000000" "0000000000000000016345785d8a0000" "00000000000000000000000000000000" "00000000000000000000000000000062" ), } ), ] chain_id = ChainID.ROPSTEN transaction_hash = ( "0x" "330df22df6543c9816d80e582a4213b1" "fc11992f317be71775f49c3d853ed5be" ) with mock.patch( "web3.eth.Eth.getTransactionReceipt" ) as m_getTransactionReceipt, mock.patch( "etherscan.contracts.Contract.get_abi", side_effect=self.m_get_abi, autospec=True, ): m_getTransactionReceipt.return_value.logs = mocked_logs decoded_methods = TransactionDebugger.decode_transaction_logs( chain_id, transaction_hash ) assert len(decoded_methods) == 2 decoded_method = decoded_methods[0] assert decoded_method["method_info"]["definition"] == ( "Log1(" "address,bytes32,uint256,string,string,uint256,bytes1,uint256)" ) decoded_method = decoded_methods[1] assert decoded_method["method_info"]["definition"] == ( "LogBet(bytes32,address,uint256,uint256,uint256,uint256)" )
def test_decode_transaction_logs(self): """ Mocking `web3.eth.Eth.getTransactionReceipt()` response and verifies decoding transaction works as expected. """ mocked_logs = [ AttributeDict({ 'address': '0xCBf1735Aad8C4B337903cD44b419eFE6538aaB40', 'topics': [ HexBytes('b76d0edd90c6a07aa3ff7a222d7f5933' 'e29c6acc660c059c97837f05c4ca1a84') ], 'data': '000000000000000000000000fe8a5f3a7bb446e1cb4566717691cd3139289ed4' 'b0230ab70b78e47050766089ea333f2ff7ad41c6f31e8bed8c2acfcb8e911841' '0000000000000000000000000000000000000000000000000000000000000000' '0000000000000000000000000000000000000000000000000000000000000100' '0000000000000000000000000000000000000000000000000000000000000140' '00000000000000000000000000000000000000000000000000000000000395f8' '1100000000000000000000000000000000000000000000000000000000000000' '00000000000000000000000000000000000000000000000000000004a817c800' '0000000000000000000000000000000000000000000000000000000000000006' '6e65737465640000000000000000000000000000000000000000000000000000' '00000000000000000000000000000000000000000000000000000000000001b4' '5b55524c5d205b276a736f6e2868747470733a2f2f6170692e72616e646f6d2e' '6f72672f6a736f6e2d7270632f312f696e766f6b65292e726573756c742e7261' '6e646f6d5b2273657269616c4e756d626572222c2264617461225d272c20275c' '6e7b226a736f6e727063223a22322e30222c226d6574686f64223a2267656e65' '726174655369676e6564496e746567657273222c22706172616d73223a7b2261' '70694b6579223a247b5b646563727970745d20424b6733544373376c6b7a4e72' '316b523670786a50434d32534f656a63466f6a55504d544f73426b432f343748' '485066317350326f78564c546a4e42752b736c523953675a797144746a564f56' '35597a67313269556b62756270304470636a434564654a54486e477743366744' '3732394755566f47766f393668757877526f5a6c436a594f3830725771325747' '596f522f4c433357616d704475767632426f3d7d2c226e223a312c226d696e22' '3a312c226d6178223a3130302c227265706c6163656d656e74223a747275652c' '2262617365223a3130247b5b6964656e746974795d20227d227d2c226964223a' '31247b5b6964656e746974795d20227d227d275d000000000000000000000000', }), AttributeDict({ 'address': '0xFE8a5f3a7Bb446e1cB4566717691cD3139289ED4', 'topics': [ HexBytes('1cb5bfc4e69cbacf65c8e05bdb84d7a3' '27bd6bb4c034ff82359aefd7443775c4'), HexBytes('b0230ab70b78e47050766089ea333f2f' 'f7ad41c6f31e8bed8c2acfcb8e911841'), HexBytes('00000000000000000000000066d4bacf' 'e61df23be813089a7a6d1a749a5c936a'), HexBytes('00000000000000000000000000000000' '0000000000000000016a98b78c556c34') ], 'data': '0000000000000000000000000000000000000000000000000007533f2ecb6c34' '000000000000000000000000000000000000000000000000016345785d8a0000' '0000000000000000000000000000000000000000000000000000000000000062', }) ] chain_id = ChainID.ROPSTEN transaction_hash = ( "0x330df22df6543c9816d80e582a4213b1fc11992f317be71775f49c3d853ed5be" ) with \ mock.patch('web3.eth.Eth.getTransactionReceipt') \ as m_getTransactionReceipt, \ mock.patch( 'etherscan.contracts.Contract.get_abi', side_effect=self.m_get_abi, autospec=True): m_getTransactionReceipt.return_value.logs = mocked_logs decoded_methods = TransactionDebugger.decode_transaction_logs( chain_id, transaction_hash) self.assertEqual(len(decoded_methods), 2) decoded_method = decoded_methods[0] self.assertEqual( decoded_method['method_info']['definition'], 'Log1(address,bytes32,uint256,string,string,uint256,bytes1,uint256)' ) decoded_method = decoded_methods[1] self.assertEqual( decoded_method['method_info']['definition'], 'LogBet(bytes32,address,uint256,uint256,uint256,uint256)')
def test_decode_method_log_bet(self): """ Trying to decode a `LogBet()` event call. """ # simplified contract ABI contract_abi = [ { 'inputs': [{ 'type': 'uint256', 'name': 'newMaxProfitAsPercent' }], 'constant': False, 'name': 'ownerSetMaxProfitAsPercentOfHouse', 'outputs': [], 'stateMutability': 'nonpayable', 'payable': False, 'type': 'function' }, { 'inputs': [], 'constant': True, 'name': 'treasury', 'outputs': [{ 'type': 'address', 'name': '' }], 'stateMutability': 'view', 'payable': False, 'type': 'function' }, { 'inputs': [], 'constant': True, 'name': 'totalWeiWagered', 'outputs': [{ 'type': 'uint256', 'name': '' }], 'stateMutability': 'view', 'payable': False, 'type': 'function' }, { 'inputs': [{ 'type': 'uint256', 'name': 'newMinimumBet' }], 'constant': False, 'name': 'ownerSetMinBet', 'outputs': [], 'stateMutability': 'nonpayable', 'payable': False, 'type': 'function' }, { 'stateMutability': 'nonpayable', 'inputs': [], 'type': 'constructor', 'payable': False }, { 'stateMutability': 'payable', 'payable': True, 'type': 'fallback' }, { 'inputs': [{ 'indexed': True, 'type': 'bytes32', 'name': 'BetID' }, { 'indexed': True, 'type': 'address', 'name': 'PlayerAddress' }, { 'indexed': True, 'type': 'uint256', 'name': 'RewardValue' }, { 'indexed': False, 'type': 'uint256', 'name': 'ProfitValue' }, { 'indexed': False, 'type': 'uint256', 'name': 'BetValue' }, { 'indexed': False, 'type': 'uint256', 'name': 'PlayerNumber' }], 'type': 'event', 'name': 'LogBet', 'anonymous': False }, ] topics = [ HexBytes( '1cb5bfc4e69cbacf65c8e05bdb84d7a327bd6bb4c034ff82359aefd7443775c4' ), HexBytes( 'b0230ab70b78e47050766089ea333f2ff7ad41c6f31e8bed8c2acfcb8e911841' ), HexBytes( '00000000000000000000000066d4bacfe61df23be813089a7a6d1a749a5c936a' ), HexBytes( '000000000000000000000000000000000000000000000000016a98b78c556c34' ), ] log_data = ( '0x' '0000000000000000000000000000000000000000000000000007533f2ecb6c34' '000000000000000000000000000000000000000000000000016345785d8a0000' '0000000000000000000000000000000000000000000000000000000000000062') transaction_debugger = TransactionDebugger(contract_abi) decoded_method = transaction_debugger.decode_method(topics, log_data) self.assertEqual( decoded_method['call'], { 'BetID': (b'\xb0#\n\xb7\x0bx\xe4pPv`\x89\xea3?/\xf7\xadA\xc6\xf3\x1e\x8b' b'\xed\x8c*\xcf\xcb\x8e\x91\x18A'), 'BetValue': 100000000000000000, 'PlayerAddress': '0x66d4bacfe61df23be813089a7a6d1a749a5c936a', 'PlayerNumber': 98, 'ProfitValue': 2061855670103092, 'RewardValue': 102061855670103092 }) self.assertEqual( decoded_method['method_info']['definition'], 'LogBet(bytes32,address,uint256,uint256,uint256,uint256)') self.assertEqual( decoded_method['method_info']['sha3'].hex(), '0x1cb5bfc4e69cbacf65c8e05bdb84d7a327bd6bb4c034ff82359aefd7443775c4' )
def test_decode_method_log1(self): """ Trying to decode a `Log1()` event call. """ # simplified contract ABI for tests contract_abi = [{ 'inputs': [], 'type': 'constructor', 'payable': False }, { 'payable': False, 'type': 'fallback' }, { 'inputs': [{ 'indexed': False, 'type': 'address', 'name': 'sender' }, { 'indexed': False, 'type': 'bytes32', 'name': 'cid' }, { 'indexed': False, 'type': 'uint256', 'name': 'timestamp' }, { 'indexed': False, 'type': 'string', 'name': 'datasource' }, { 'indexed': False, 'type': 'string', 'name': 'arg' }, { 'indexed': False, 'type': 'uint256', 'name': 'gaslimit' }, { 'indexed': False, 'type': 'bytes1', 'name': 'proofType' }, { 'indexed': False, 'type': 'uint256', 'name': 'gasPrice' }], 'type': 'event', 'name': 'Log1', 'anonymous': False }, { 'inputs': [{ 'indexed': False, 'type': 'address', 'name': 'sender' }, { 'indexed': False, 'type': 'bytes32', 'name': 'cid' }, { 'indexed': False, 'type': 'uint256', 'name': 'timestamp' }, { 'indexed': False, 'type': 'string', 'name': 'datasource' }, { 'indexed': False, 'type': 'string', 'name': 'arg1' }, { 'indexed': False, 'type': 'string', 'name': 'arg2' }, { 'indexed': False, 'type': 'uint256', 'name': 'gaslimit' }, { 'indexed': False, 'type': 'bytes1', 'name': 'proofType' }, { 'indexed': False, 'type': 'uint256', 'name': 'gasPrice' }], 'type': 'event', 'name': 'Log2', 'anonymous': False }, { 'inputs': [{ 'indexed': False, 'type': 'address', 'name': 'sender' }, { 'indexed': False, 'type': 'bytes32', 'name': 'cid' }, { 'indexed': False, 'type': 'uint256', 'name': 'timestamp' }, { 'indexed': False, 'type': 'string', 'name': 'datasource' }, { 'indexed': False, 'type': 'bytes', 'name': 'args' }, { 'indexed': False, 'type': 'uint256', 'name': 'gaslimit' }, { 'indexed': False, 'type': 'bytes1', 'name': 'proofType' }, { 'indexed': False, 'type': 'uint256', 'name': 'gasPrice' }], 'type': 'event', 'name': 'LogN', 'anonymous': False }] topics = [ HexBytes( 'b76d0edd90c6a07aa3ff7a222d7f5933e29c6acc660c059c97837f05c4ca1a84' ) ] log_data = ( "0x" "000000000000000000000000fe8a5f3a7bb446e1cb4566717691cd3139289ed4" "b0230ab70b78e47050766089ea333f2ff7ad41c6f31e8bed8c2acfcb8e911841" "0000000000000000000000000000000000000000000000000000000000000000" "0000000000000000000000000000000000000000000000000000000000000100" "0000000000000000000000000000000000000000000000000000000000000140" "00000000000000000000000000000000000000000000000000000000000395f8" "1100000000000000000000000000000000000000000000000000000000000000" "00000000000000000000000000000000000000000000000000000004a817c800" "0000000000000000000000000000000000000000000000000000000000000006" "6e65737465640000000000000000000000000000000000000000000000000000" "00000000000000000000000000000000000000000000000000000000000001b4" "5b55524c5d205b276a736f6e2868747470733a2f2f6170692e72616e646f6d2e" "6f72672f6a736f6e2d7270632f312f696e766f6b65292e726573756c742e7261" "6e646f6d5b2273657269616c4e756d626572222c2264617461225d272c20275c" "6e7b226a736f6e727063223a22322e30222c226d6574686f64223a2267656e65" "726174655369676e6564496e746567657273222c22706172616d73223a7b2261" "70694b6579223a247b5b646563727970745d20424b6733544373376c6b7a4e72" "316b523670786a50434d32534f656a63466f6a55504d544f73426b432f343748" "485066317350326f78564c546a4e42752b736c523953675a797144746a564f56" "35597a67313269556b62756270304470636a434564654a54486e477743366744" "3732394755566f47766f393668757877526f5a6c436a594f3830725771325747" "596f522f4c433357616d704475767632426f3d7d2c226e223a312c226d696e22" "3a312c226d6178223a3130302c227265706c6163656d656e74223a747275652c" "2262617365223a3130247b5b6964656e746974795d20227d227d2c226964223a" "31247b5b6964656e746974795d20227d227d275d000000000000000000000000") transaction_debugger = TransactionDebugger(contract_abi) decoded_method = transaction_debugger.decode_method(topics, log_data) # TODO: simplify that arg call for unit testing self.assertEqual( decoded_method['call'], { 'arg': bytes( '[URL] [\'json(https://api.random.org/json-rpc/1/invoke).resul' 't.random["serialNumber","data"]\', \'\\n{"jsonrpc":"2.0","met' 'hod":"generateSignedIntegers","params":{"apiKey":${[decrypt] ' 'BKg3TCs7lkzNr1kR6pxjPCM2SOejcFojUPMTOsBkC/47HHPf1sP2oxVLTjNBu' '+slR9SgZyqDtjVOV5Yzg12iUkbubp0DpcjCEdeJTHnGwC6gD729GUVoGvo96h' 'uxwRoZlCjYO80rWq2WGYoR/LC3WampDuvv2Bo=},"n":1,"min":1,"max":1' '00,"replacement":true,"base":10${[identity] "}"},"id":1${[ide' 'ntity] "}"}\']', "utf8"), 'cid': (b'\xb0#\n\xb7\x0bx\xe4pPv`\x89\xea3?/\xf7\xadA\xc6\xf3\x1e' b'\x8b\xed\x8c*\xcf\xcb\x8e\x91\x18A'), 'datasource': b'nested', 'gasPrice': 20000000000, 'gaslimit': 235000, 'proofType': b'\x11', 'sender': '0xfe8a5f3a7bb446e1cb4566717691cd3139289ed4', 'timestamp': 0 }) self.assertEqual( decoded_method['method_info']['definition'], 'Log1(address,bytes32,uint256,string,string,uint256,bytes1,uint256)' ) self.assertEqual( decoded_method['method_info']['sha3'].hex(), '0xb76d0edd90c6a07aa3ff7a222d7f5933e29c6acc660c059c97837f05c4ca1a84' )
def __hash(cls, payload: bytes) -> HexBytes: blake = hashlib.blake2b() blake.update(payload) digest = blake.digest().hex() truncated_digest = digest[:cls.__ID_LENGTH] return HexBytes(truncated_digest)
def sign_message(self, account: str, message: bytes, **kwargs) -> HexBytes: signature = self.__client.sign_message(account=account, message=message) return HexBytes(signature)