def upload(self, relativeFilePath, lookupKey = None, signatureKey = None, constructorArgs=[]): resolvedPath = resolveRelativePath(relativeFilePath) if self.coverageMode: resolvedPath = resolvedPath.replace("tests", "coverageEnv").replace("source/", "coverageEnv/") lookupKey = lookupKey if lookupKey else path.splitext(path.basename(resolvedPath))[0] signatureKey = signatureKey if signatureKey else lookupKey if lookupKey in self.contracts: return(self.contracts[lookupKey]) compiledCode = self.getCompiledCode(resolvedPath) # abstract contracts have a 0-length array for bytecode if len(compiledCode) == 0: if ("libraries" in relativeFilePath or lookupKey.startswith("I") or lookupKey.startswith("Base")): pass#print "Skipping upload of " + lookupKey + " because it had no bytecode (likely a abstract class/interface)." else: raise Exception("Contract: " + lookupKey + " has no bytecode, but this is not expected. It probably doesn't implement all its abstract methods") return None if signatureKey not in ContractsFixture.signatures: ContractsFixture.signatures[signatureKey] = self.generateSignature(resolvedPath) signature = ContractsFixture.signatures[signatureKey] contractTranslator = ContractTranslator(signature) if len(constructorArgs) > 0: compiledCode += contractTranslator.encode_constructor_arguments(constructorArgs) contractAddress = bytesToHexString(self.chain.contract(compiledCode, language='evm')) contract = ABIContract(self.chain, contractTranslator, contractAddress) self.contracts[lookupKey] = contract return(contract)
def all_contract_events(rpc, contract_address, abi, start_block=None, end_block=None): """Find and decode all events for a deployed contract given its `contract_address` and `abi`. Args: rpc (pyethapp.rpc_client.JSONRPCClient): client instance. contract_address (string): hex encoded contract address. abi (list(dict)): the contract's ABI. start_block (int): read event-logs starting from this block number. end_block (int): read event-logs up to this block number. Returns: events (list) """ translator = ContractTranslator(abi) events_raw = all_contract_events_raw( rpc, contract_address, start_block=start_block, end_block=end_block, ) events = list() for event_encoded in events_raw: topics_ids = [ decode_topic(topic) for topic in event_encoded['topics'] ] event_data = data_decoder(event_encoded['data']) event = translator.decode_event(topics_ids, event_data) events.append(event) return events
def abi_contract(self, sourcecode, sender=DEFAULT_KEY, endowment=0, # pylint: disable=too-many-arguments language='serpent', log_listener=None, listen=True, libraries=None, path=None, constructor_parameters=None, **kwargs): # pylint: disable=too-many-locals compiler = languages[language] contract_interface = compiler.mk_full_signature(sourcecode, path=path, **kwargs) translator = ContractTranslator(contract_interface) encoded_parameters = None if constructor_parameters is not None: encoded_parameters = translator.encode_constructor_arguments(constructor_parameters) address = self.contract( sourcecode, sender, endowment, language, libraries, path, constructor_call=encoded_parameters, **kwargs ) return ABIContract( self, translator, address, listen=listen, log_listener=log_listener, )
def applySignature(self, signatureName, address): assert address if type(address) is long: address = longToHexString(address) translator = ContractTranslator( ContractsFixture.signatures[signatureName]) contract = ABIContract(self.chain, translator, address) return contract
def getShareToken(self, market, outcome): shareTokenAddress = market.getShareToken(outcome) assert shareTokenAddress shareToken = ABIContract( self.chain, ContractTranslator(ContractsFixture.signatures['ShareToken']), shareTokenAddress) return shareToken
def __init__(self, *, abi, address, translator=None, log_filter_id=None): self.abi = abi self.valid_funcs = [ part['name'] for part in abi if part['type'] == 'function' ] self.translator = translator or ContractTranslator(abi) self.address = address self.log_filter_id = log_filter_id
def do_transaction(json_rpc, coinbase, contract, name, params, gas, gas_price, private_key): contract_address = addresses[ contract] if contract in addresses else contract contract_abi = abis[contract] translator = ContractTranslator(contract_abi) data = translator.encode(name, [ addresses[param] if param in addresses else param for param in params ]).encode("hex") print 'Try to send {} transaction to contract {}.'.format(name, contract) if private_key: address = privtoaddr(private_key.decode('hex')) nonce = int( json_rpc.eth_getTransactionCount('0x' + address.encode('hex')) ["result"][2:], 16) tx = Transaction(nonce, gas_price, gas, contract_address, 0, data.decode('hex')) tx.sign(private_key.decode('hex')) raw_tx = rlp.encode(tx).encode('hex') # transaction_hash = json_rpc.eth_sendRawTransaction("0x" + raw_tx)["result"] tx_response = json_rpc.eth_sendRawTransaction("0x" + raw_tx) while 'error' in tx_response: print 'Transaction failed with error {}. Retry!'.format( tx_response['error']) time.sleep(5) tx_response = json_rpc.eth_sendRawTransaction("0x" + raw_tx) else: # transaction_hash = json_rpc.eth_sendTransaction(coinbase, to_address=contract_address, data=data, gas=gas, gas_price=gas_price)["result"] tx_response = json_rpc.eth_sendTransaction(coinbase, to_address=contract_address, data=data, gas=gas, gas_price=gas_price) while 'error' in tx_response: print 'Transaction failed with error {}. Retry!'.format( tx_response['error']) time.sleep(5) tx_response = json_rpc.eth_sendTransaction( coinbase, to_address=contract_address, data=data, gas=gas, gas_price=gas_price) transaction_hash = tx_response['result'] wait_for_transaction_receipt(json_rpc, transaction_hash) print 'Transaction {} for contract {} completed.'.format(name, contract)
def __init__(self, address: str, interface: Sequence[Mapping], rpc_address: str, sender: str = None, gas: int = MAX_GAS): """Create a new Contract instance. Batch requests not supported! Arguments: address -- The address of the smart contract you want to use. interface -- The full signature of the smart contract. rpc_address -- The address of the RPC server for your Ethereum node. sender -- The address to send from. If None, the default sender for your node is used. gas -- The maximum amount of gas to use per transaction/call. """ err_fmt = 'Invalid {} address, must be 40 digit hex starting with \'0x\': {!r}' if not ETH_ADDR.match(address): raise ContractError(err_fmt.format('contract', address)) self.translator = ContractTranslator(interface) self.rpc_client = rpc_factory(rpc_address, False) self.common_params = {'to': address, 'gas': hex(gas)} if sender is None: pass elif ETH_ADDR.match(sender): self.common_params['from'] = sender else: raise ContractError(err_fmt.format('sender', sender)) def proxy_factory(name): # Generates proxy functions that use rpc methods under the hood. pyname = name.split('(')[0] # a python compatible name def proxy(*args, **kwds): """Calls function {} in contract {}. If the optional `call` keyword is True, then the result of the function call is decoded into a Python object and returned, otherwise the transaction hash is returned. """ tx = self.common_params.copy() data = self.translator.encode_function_call(pyname, args) tx['data'] = '0x{}'.format(data.encode('hex')) if kwds.get('call', False): return self._call(pyname, tx) else: return self._send(tx) proxy.__name__ = pyname proxy.__doc__ = proxy.__doc__.format(name, address) return proxy for item in interface: if item['type'] == 'function': proxy = proxy_factory(item['name']) if hasattr(self, proxy.__name__): raise ContractError('Polymorphism not supported!') setattr(self, proxy.__name__, proxy)
def uploadSolidityContract(chain, compileResult, name, contractName): print compileResult['contracts'][name][contractName]['evm']['bytecode'][ 'object'] bytecode = bytearray.fromhex(compileResult['contracts'][name][contractName] ['evm']['bytecode']['object']) signature = compileResult['contracts'][name][contractName]['abi'] address = long(hexlify(chain.contract(bytecode, language='evm')), 16) contract = ABIContract(chain, ContractTranslator(signature), address) return contract
def __init__(self, tokens): self.client = JSONRPCClient( privkey=None, host=host, port=port, print_communication=False, ) self.wallet_translator = ContractTranslator(wallet_abi) self.tokens = tokens
def do_assertion(json_rpc, contract, name, params, return_value): contract_address = addresses[ contract] if contract in addresses else contract return_value = addresses[ return_value] if return_value in addresses else return_value contract_abi = abis[contract] translator = ContractTranslator(contract_abi) data = translator.encode(name, [ addresses[param] if param in addresses else param for param in params ]).encode("hex") print 'Try to assert return value of {} in contract {}.'.format( name, contract) bc_return_val = json_rpc.eth_call(to_address=contract_address, data=data)["result"] result_decoded = translator.decode(name, bc_return_val[2:].decode("hex")) result_decoded = result_decoded if len( result_decoded) > 1 else result_decoded[0] assert result_decoded == return_value[2:]
def get_contract_data(contract_name, ctor_args): bin_file = open(contract_name + ".bin", "rb") bin = h2b(bin_file.read()) # print bin bin_file.close() bin = h2b("6060604052341561000c57fe5b5b5b5b6103b08061001e6000396000f300606060405263ffffffff60e060020a6000350416631e5e2d8f81146100425780637789139314610069578063d40f1da21461007e578063de9702a4146100a5575bfe5b341561004a57fe5b610067600435602435600160a060020a03604435166064356100ef565b005b341561007157fe5b610067600435610162565b005b341561008657fe5b6100916004356101f8565b604080519115158252519081900360200190f35b34156100ad57fe5b6100b8600435610276565b60408051600160a060020a039687168152949095166020850152838501929092526060830152608082015290519081900360a00190f35b600060008281548110151561010057fe5b906000526020600020906005020160005b50805490915033600160a060020a0390811691161461012f57610000565b600181018054600160a060020a031916600160a060020a03851617905560028101859055600381018490555b5050505050565b61016a6102c3565b600160a060020a033316815260808101829052600080546001810161018f8382610305565b916000526020600020906005020160005b5082518154600160a060020a03918216600160a060020a0319918216178355602085015160018401805491909316911617905560408301516002820155606083015160038201556080830151600490910155505b5050565b6000600060008381548110151561020b57fe5b906000526020600020906005020160005b50600181015490915033600160a060020a039081169116146102415760009150610270565b80600201544210156102565760009150610270565b806003015442111561026b5760009150610270565b600191505b50919050565b600080548290811061028457fe5b906000526020600020906005020160005b508054600182015460028301546003840154600490940154600160a060020a03938416955091909216929085565b60a0604051908101604052806000600160a060020a031681526020016000600160a060020a031681526020016000815260200160008152602001600081525090565b815481835581811511610331576005028160050283600052602060002091820191016103319190610337565b5b505050565b61038191905b8082111561037d578054600160a060020a03199081168255600182018054909116905560006002820181905560038201819055600482015560050161033d565b5090565b905600a165627a7a72305820c2389efff0fcf3752969acca63721798524aa30be1bcda35155b682da37f83b20029") abi_file = open(contract_name + ".abi", "r") abi = abi_file.read() abi_file.close() translator = ContractTranslator(abi) ctor_call = translator.encode_constructor_arguments(ctor_args) #print "ctor" #print b2h(ctor_call) return (bin + ctor_call, abi)
def send_transaction(self, _from, to, value, name, params, abi): reference = to to = self.replace_references(to) data = '' if name or abi: if not name: name = abi['name'] abi = self.abis[to] if to in self.abis else [abi] translator = ContractTranslator(abi) data = encode( translator.encode(name, self.replace_references(params)), "hex") self.log('Transaction to {}{} sent'.format( self.format_reference(reference), ' calling {} function'.format(name) if name else '')) tx_response = None if self.private_key: raw_tx = self.get_raw_transaction(to=to, value=value, data=data) while tx_response is None or 'error' in tx_response: if tx_response and 'error' in tx_response: self.log('Transaction failed with error {}'.format( tx_response['error']['message'])) time.sleep(5) tx_response = self.json_rpc.eth_sendRawTransaction(raw_tx) else: while tx_response is None or 'error' in tx_response: if tx_response and 'error' in tx_response: self.log('Transaction failed with error {}'.format( tx_response['error']['message'])) time.sleep(5) tx_response = self.json_rpc.eth_sendTransaction( self.add_0x(_from if _from else self._from), to_address=self.add_0x(to), value=value, data=self.add_0x(data), gas=self.gas, gas_price=self.gas_price) transaction_hash = tx_response['result'] transaction_receipt = self.wait_for_transaction_receipt( self.add_0x(transaction_hash)) self.log('Transaction to {}{} successful'.format( self.format_reference(reference), ' calling {} function'.format(name) if name else '')) self.log_transaction_receipt(transaction_receipt)
def call_function( self, priv_key, value, contract_hash, contract_abi, function_name, eth_args, use_increased_gas_price=False, ): translator = ContractTranslator(json.loads(contract_abi)) call = translator.encode_function_call(function_name, eth_args) return self._make_transaction( src_priv_key=priv_key, dst_address=contract_hash, value=value, data=call, use_increased_gas_price=use_increased_gas_price, )
def get_token_network_events(self, token_address, from_block, to_block=''): # Note: Issue #452 (https://github.com/raiden-network/raiden/issues/452) # tracks a suggested TODO, which will reduce the 3 RPC calls here to only # one using `eth_getLogs`. It will require changes in all testing frameworks # to be implemented though. translator = ContractTranslator(CHANNEL_MANAGER_ABI) token_address_bin = address_decoder(token_address) channel_manager = self.raiden.chain.manager_by_token(token_address_bin) filter_ = None try: filter_ = channel_manager.channelnew_filter(from_block, to_block) events = filter_.getall() finally: if filter_ is not None: filter_.uninstall() return [ translator.decode_event(event['topics'], event['data']) for event in events ]
def get_network_events(self, from_block, to_block=''): # Note: Issue #452 (https://github.com/raiden-network/raiden/issues/452) # tracks a suggested TODO, which will reduce the 3 RPC calls here to only # one using `eth_getLogs`. It will require changes in all testing frameworks # to be implemented though. # Assuming only one token registry for the moment translator = ContractTranslator(REGISTRY_ABI) filter_ = None try: filter_ = self.raiden.registries[0].tokenadded_filter( from_block, to_block) events = filter_.getall() finally: if filter_ is not None: filter_.uninstall() return [ translator.decode_event(event['topics'], event['data']) for event in events ]
def getOrCreateChildUniverse(self, parentUniverse, market, payoutDistribution): assert payoutDistributionHash childUniverseAddress = parentUniverse.getOrCreateChildUniverse( payoutDistribution) assert childUniverseAddress childUniverse = ABIContract( self.chain, ContractTranslator(ContractsFixture.signatures['Universe']), childUniverseAddress) return childUniverse
def create_contract(path, args=None, sender=t.k0): t.s.mine() contract_name = path.split('/')[1] contract_name += ':' + contract_name.split('.')[0] path, extra_args = get_dirs(path) if args: args = [ x.address if isinstance(x, t.ABIContract) else x for x in args ] compiler = t.languages['solidity'] combined = _solidity.compile_file(path, combined='bin,abi', optimize=True, extra_args=extra_args) abi = combined[contract_name]['abi'] ct = ContractTranslator(abi) code = combined[contract_name]['bin'] + ( ct.encode_constructor_arguments(args) if args else b'') address = t.s.tx(sender=sender, to=b'', value=0, data=code) return t.ABIContract(t.s, abi, address)
def assert_call(self, contract, name, params, return_value): contract_address = self.replace_address(contract) return_value = self.replace_address(return_value) contract_abi = self.contract_abis[contract] translator = ContractTranslator(contract_abi) data = translator.encode(name, [self.replace_address(p) for p in params]).encode("hex") logging.info('Try to assert return value of {} in contract {}.'.format( name, contract)) bc_return_val = self.json_rpc.eth_call(to_address=contract_address, data=data)["result"] result_decoded = translator.decode(name, bc_return_val[2:].decode("hex")) result_decoded = result_decoded if len( result_decoded) > 1 else result_decoded[0] assert result_decoded == return_value logging.info( 'Assertion successful for return value of {} in contract {}.'. format(name, contract))
def upload(self, relativeFilePath, lookupKey=None, signatureKey=None, constructorArgs=[]): resolvedPath = resolveRelativePath(relativeFilePath) if self.coverageMode: resolvedPath = resolvedPath.replace("tests", "coverageEnv").replace( "source/", "coverageEnv/") lookupKey = lookupKey if lookupKey else path.splitext( path.basename(resolvedPath))[0] signatureKey = signatureKey if signatureKey else lookupKey if lookupKey in self.contracts: return (self.contracts[lookupKey]) compiledCode = self.getCompiledCode(resolvedPath) # abstract contracts have a 0-length array for bytecode if len(compiledCode) == 0: if ("libraries" in relativeFilePath or lookupKey.startswith("I") or lookupKey.startswith("Base") or lookupKey.startswith("DS")): pass #print "Skipping upload of " + lookupKey + " because it had no bytecode (likely a abstract class/interface)." else: raise Exception( "Contract: " + lookupKey + " has no bytecode, but this is not expected. It probably doesn't implement all its abstract methods" ) return None if signatureKey not in ContractsFixture.signatures: ContractsFixture.signatures[signatureKey] = self.generateSignature( resolvedPath) signature = ContractsFixture.signatures[signatureKey] contractTranslator = ContractTranslator(signature) if len(constructorArgs) > 0: compiledCode += contractTranslator.encode_constructor_arguments( constructorArgs) contractAddress = bytesToHexString( self.chain.contract(compiledCode, language='evm')) contract = ABIContract(self.chain, contractTranslator, contractAddress) self.contracts[lookupKey] = contract return (contract)
def abi_contract( self, sourcecode, sender=DEFAULT_KEY, endowment=0, # pylint: disable=too-many-arguments language='serpent', log_listener=None, listen=True, libraries=None, path=None, constructor_parameters=None, **kwargs): # pylint: disable=too-many-locals compiler = languages[language] contract_interface = compiler.mk_full_signature(sourcecode, path=path, **kwargs) translator = ContractTranslator(contract_interface) encoded_parameters = None if constructor_parameters is not None: encoded_parameters = translator.encode_constructor_arguments( constructor_parameters) address = self.contract(sourcecode, sender, endowment, language, libraries, path, constructor_call=encoded_parameters, **kwargs) return ABIContract( self, translator, address, listen=listen, log_listener=log_listener, )
def upload(self, relativeFilePath, lookupKey = None, signatureKey = None, constructorArgs=[]): resolvedPath = resolveRelativePath(relativeFilePath) lookupKey = lookupKey if lookupKey else path.splitext(path.basename(resolvedPath))[0] signatureKey = signatureKey if signatureKey else lookupKey if lookupKey in self.contracts: return(self.contracts[lookupKey]) compiledCode = ContractsFixture.getCompiledCode(resolvedPath) # abstract contracts have a 0-length array for bytecode if len(compiledCode) == 0: print "Skipping upload of " + lookupKey + " because it had no bytecode (likely a abstract class/interface)." return None if signatureKey not in ContractsFixture.signatures: ContractsFixture.signatures[signatureKey] = ContractsFixture.generateSignature(resolvedPath) signature = ContractsFixture.signatures[signatureKey] contractTranslator = ContractTranslator(signature) if len(constructorArgs) > 0: compiledCode += contractTranslator.encode_constructor_arguments(constructorArgs) contractAddress = bytesToHexString(self.chain.contract(compiledCode, language='evm', startgas=long(6.7 * 10**6))) contract = ABIContract(self.chain, contractTranslator, contractAddress) self.contracts[lookupKey] = contract return(contract)
def deploy_solidity_contract_with_args(chain, solc_config_sources, allow_paths, contract_file, contract_name, startgas, args=[], contract_creator=tester.k0): compiled = compile_standard({ 'language': 'Solidity', 'sources': solc_config_sources, 'settings': {'evmVersion': 'byzantium', 'outputSelection': {'*': {'*': ['abi', 'evm.bytecode']}}, }, }, allow_paths=allow_paths) abi = compiled['contracts'][contract_file][contract_name]['abi'] binary = compiled['contracts'][contract_file][contract_name]['evm']['bytecode']['object'] ct = ContractTranslator(abi) address = chain.contract( utils.decode_hex(binary) + (ct.encode_constructor_arguments(args) if args else b''), language='evm', value=0, startgas=startgas, sender=contract_creator ) contract = tester.ABIContract(chain, ct, address) return contract
def create_contract(path, args=(), sender=ethtester.k0): abi, hexcode = deployer.get_contract_data(path) bytecode = ethutils.decode_hex(hexcode) encoded_args = ( ContractTranslator(abi).encode_constructor_arguments(args) if args else b'') code = bytecode + encoded_args address = ethtester.chain.tx(sender=sender, to=b'', startgas=START_GAS, data=code) return ethtester.ABIContract(ethtester.chain, abi, address)
def setup(host, port, contract, gas, gas_price, private_key): gas = int(gas) gas_price = int(gas_price) json_rpc = EthJsonRpc(host, port) coinbase = json_rpc.eth_coinbase()["result"] if private_key: print "Your address for your private key: {}".format( privtoaddr(private_key.decode('hex')).encode('hex')) else: print "Your coinbase: {}".format(coinbase) contract_abi = json.loads( '[{"inputs": [], "constant": true, "type": "function", "name": "startDate", "outputs": [{"type": "uint256", "name": ""}]}, {"inputs": [], "constant": true, "type": "function", "name": "CROWDFUNDING_PERIOD", "outputs": [{"type": "uint256", "name": ""}]}, {"inputs": [], "constant": false, "type": "function", "name": "emergencyCall", "outputs": [{"type": "bool", "name": ""}]}, {"inputs": [{"type": "address", "name": "singularDTVFundAddress"}, {"type": "address", "name": "singularDTVTokenAddress"}], "constant": false, "type": "function", "name": "setup", "outputs": [{"type": "bool", "name": ""}]}, {"inputs": [], "constant": false, "type": "function", "name": "withdrawFunding", "outputs": [{"type": "bool", "name": ""}]}, {"inputs": [], "constant": true, "type": "function", "name": "fundBalance", "outputs": [{"type": "uint256", "name": ""}]}, {"inputs": [], "constant": true, "type": "function", "name": "singularDTVFund", "outputs": [{"type": "address", "name": ""}]}, {"inputs": [], "constant": true, "type": "function", "name": "baseValue", "outputs": [{"type": "uint256", "name": ""}]}, {"inputs": [], "constant": true, "type": "function", "name": "TOKEN_TARGET", "outputs": [{"type": "uint256", "name": ""}]}, {"inputs": [], "constant": true, "type": "function", "name": "singularDTVToken", "outputs": [{"type": "address", "name": ""}]}, {"inputs": [], "constant": true, "type": "function", "name": "owner", "outputs": [{"type": "address", "name": ""}]}, {"inputs": [{"type": "uint256", "name": "valueInWei"}], "constant": false, "type": "function", "name": "changeBaseValue", "outputs": [{"type": "bool", "name": ""}]}, {"inputs": [{"type": "address", "name": ""}], "constant": true, "type": "function", "name": "investments", "outputs": [{"type": "uint256", "name": ""}]}, {"inputs": [], "constant": false, "type": "function", "name": "fund", "outputs": [{"type": "uint256", "name": ""}]}, {"inputs": [], "constant": true, "type": "function", "name": "stage", "outputs": [{"type": "uint8", "name": ""}]}, {"inputs": [], "constant": false, "type": "function", "name": "updateStage", "outputs": [{"type": "uint8", "name": ""}]}, {"inputs": [], "constant": true, "type": "function", "name": "valuePerShare", "outputs": [{"type": "uint256", "name": ""}]}, {"inputs": [], "constant": true, "type": "function", "name": "TOKEN_LOCKING_PERIOD", "outputs": [{"type": "uint256", "name": ""}]}, {"inputs": [], "constant": true, "type": "function", "name": "campaignEndedSuccessfully", "outputs": [{"type": "bool", "name": ""}]}, {"inputs": [], "constant": true, "type": "function", "name": "workshopWaited2Years", "outputs": [{"type": "bool", "name": ""}]}, {"inputs": [], "constant": true, "type": "function", "name": "CAP", "outputs": [{"type": "uint256", "name": ""}]}, {"inputs": [], "constant": false, "type": "function", "name": "withdrawForWorkshop", "outputs": [{"type": "bool", "name": ""}]}, {"inputs": [], "type": "constructor"}]' ) translator = ContractTranslator(contract_abi) data = translator.encode("emergencyCall", ()).encode("hex") bc_return_val = json_rpc.eth_call(to_address=contract, data=data)["result"] result_decoded = translator.decode("emergencyCall", bc_return_val[2:].decode("hex"))[0] if result_decoded: if private_key: address = privtoaddr(private_key.decode('hex')) nonce = int( json_rpc.eth_getTransactionCount('0x' + address.encode('hex')) ["result"][2:], 16) tx = Transaction(nonce, gas_price, gas, contract, 0, data.decode('hex')) tx.sign(private_key.decode('hex')) raw_tx = rlp.encode(tx).encode('hex') transaction_hash = json_rpc.eth_sendRawTransaction( "0x" + raw_tx)["result"] else: transaction_hash = json_rpc.eth_sendTransaction( coinbase, to_address=contract, data=data, gas=gas, gas_price=gas_price)["result"] wait_for_transaction_receipt(json_rpc, transaction_hash) print 'Transaction {} for contract {} completed.'.format( "emergencyCall", contract)
def contract(self, sourcecode, args=[], sender=k0, value=0, language=None, l=None, startgas=STARTGAS, gasprice=GASPRICE): assert not (l and language) language = l or language if language == 'evm': assert len(args) == 0 return self.tx(sender=sender, to=b'', value=value, data=sourcecode, startgas=startgas, gasprice=gasprice) else: compiler = languages[language] interface = compiler.mk_full_signature(sourcecode) ct = ContractTranslator(interface) code = compiler.compile( sourcecode) + (ct.encode_constructor_arguments(args) if args else b'') addr = self.tx( sender=sender, to=b'', value=value, data=code, startgas=startgas, gasprice=gasprice) return ABIContract(self, ct, addr)
class Repo(object): def __init__(self, account, infura, bin_path, abi_path): self.account = account self.infura = infura with open(bin_path, 'rb') as contract_file: contract_bin = contract_file.read().replace(b"\n", b"") self.contract_bin = binascii.unhexlify(contract_bin) with open(abi_path, 'r') as abi_file: self.contract = ContractTranslator(json.load(abi_file)) def create(self, ref_head, gasprice, startgas): constructor_args = self.contract.encode_constructor_arguments([ref_head]) tx, response = self.account.send_transaction(gasprice, startgas, self.contract_bin + constructor_args) contract_address = '0x' + encode_hex(tx.creates) return contract_address, response.json() def transact(self, contract_address, function, args, value=0, gasprice=15000000000, gaslimit=140000): txdata = self.contract.encode_function_call(function, args) tx, response = self.account.send_transaction(gasprice, gaslimit, txdata, to=contract_address, value=value) return response.json() def call(self, contract_address, function, args): txdata = self.contract.encode_function_call(function, args) params = { "params": json.dumps([{ "to": contract_address, "data": "0x" + encode_hex(txdata) }, 'latest']) } response = self.infura.get('eth_call', params).json() if 'result' in response and response['result'] == '0x': response['result'] = [] elif 'result' in response: response['result'] = self.contract.decode_function_result(function, binascii.unhexlify(response['result'][2:])) return response
def call_const_function( priv_key, value, contract_hash, contract_abi, function_name, args ): src_address = b2h( utils.privtoaddr(priv_key) ) translator = ContractTranslator(contract_abi) call = translator.encode_function_call(function_name, args) nonce = get_num_transactions( src_address ) gas_price = get_gas_price_in_wei() start_gas = eval_startgas( src_address, contract_hash, value, b2h(call), gas_price ) nonce = int( nonce, 16 ) gas_price = int( gas_price, 16 ) start_gas = int( start_gas, 16 ) + 100000 params = { "from" : "0x" + src_address, "to" : "0x" + contract_hash, "gas" : "0x" + str(start_gas), "gasPrice" : "0x" + str(gas_price), "value" : str(value), "data" : "0x" + b2h(call) } return_value = json_call( "eth_call", [params]) return_value = h2b(return_value[2:]) # remove 0x return translator.decode(function_name, return_value)
def send_transaction(self, contract, name, params): contract_address = self.replace_address(contract) contract_abi = self.contract_abis[contract] translator = ContractTranslator(contract_abi) data = translator.encode(name, [self.replace_address(p) for p in params]).encode("hex") logging.info('Try to send {} transaction to contract {}.'.format( name, contract)) if self.private_key: raw_tx = self.get_raw_transaction(data, contract_address) tx_response = self.json_rpc.eth_sendRawTransaction("0x" + raw_tx) while 'error' in tx_response: logging.info('Transaction failed with error {}. Retry!'.format( tx_response['error'])) time.sleep(5) tx_response = self.json_rpc.eth_sendRawTransaction("0x" + raw_tx) else: tx_response = self.json_rpc.eth_sendTransaction( self.user_address, to_address=contract_address, data=data, gas=self.gas, gas_price=self.gas_price) while 'error' in tx_response: logging.info('Transaction failed with error {}. Retry!'.format( tx_response['error'])) time.sleep(5) tx_response = self.json_rpc.eth_sendTransaction( self.user_address, to_address=contract_address, data=data, gas=self.gas, gas_price=self.gas_price) transaction_hash = tx_response['result'] self.wait_for_transaction_receipt(transaction_hash) logging.info('Transaction {} for contract {} completed.'.format( name, contract))
def all_contract_events( rpc: JSONRPCClient, contract_address: str, abi, start_block: Union[str, int] = 0, end_block: Union[str, int] = 'latest') -> List[Dict]: """Find and decode all events for a deployed contract given its `contract_address` and `abi`. Args: rpc: client instance. contract_address: hex encoded contract address. abi: the contract's ABI. start_block: read event-logs starting from this block number (default: 0). end_block: read event-logs up to this block number (default: 'latest'). Returns: A list of all events from the given contract. """ translator = ContractTranslator(abi) events_raw = all_contract_events_raw( rpc, contract_address, start_block=start_block, end_block=end_block ) events = list() for event_encoded in events_raw: topics_ids = [ topic_decoder(topic) for topic in event_encoded['topics'] ] event_data = data_decoder(event_encoded['data']) event = translator.decode_event(topics_ids, event_data) events.append(event) return events
def __init__(self, _chain, _abi, address): self.address = address if isinstance(_abi, ContractTranslator): abi_translator = _abi else: abi_translator = ContractTranslator(_abi) self.translator = abi_translator for function_name in self.translator.function_data: function = self.method_factory(_chain, function_name) method = types.MethodType(function, self) setattr(self, function_name, method)
def init_contracts(nodes): result = dict() tester_state = Chain() for address, contract in CONTRACTS.iteritems(): contract_path = path.join(CONTRACTS_DIR, contract['file']) simple_compiled = compile_file(contract_path) simple_data = solidity_get_contract_data( simple_compiled, contract_path, contract['name'], ) ct = ContractTranslator(simple_data['abi']) if (address == '0x00000000000000000000000000000000013241a3'): extra = (ct.encode_constructor_arguments([nodes[address]]) if nodes[address] else b'') else: extra = (ct.encode_constructor_arguments([nodes[address][0], nodes[address][1]]) if nodes[address] else b'') print(binascii.hexlify(simple_data['bin'] + extra)) abi_address = tester_state.contract(simple_data['bin'] + extra) tester_state.mine() account = tester_state.chain.state.account_to_dict(abi_address) result[address] = {'code': account['code'], 'storage': account['storage'], 'nonce': account['nonce']} return result
def init_normal_contracts(self): """Compile normal contracts from files and construct by arguments. """ flags = [ 'checkCallPermission', 'checkSendTxPermission', 'checkCreateContractPermission', 'checkQuota', 'checkFeeBackPlatform', 'autoExec' ] ncinfo = self.contracts_list['NormalContracts'] for name, info in ncinfo.items(): addr = info['address'] path = os.path.join(self.contracts_dir, info['file']) data = self.compile_to_data(name, path) self.write_docs(name, data) ctt = ContractTranslator(data['abi']) args = self.contracts_args.get(name) if name == 'SysConfig': args['flags'] = [] for flag in flags: args['flags'].append(args[flag]) args.pop(flag) extra = b'' if not args else ctt.encode_constructor_arguments( [arg for arg in args.values()]) self.mine_contract_on_chain_tester(addr, data['bin'] + extra)
def test_event(): event_abi = [{ 'name': 'Test', 'anonymous': False, 'inputs': [ { 'indexed': False, 'name': 'a', 'type': 'int256' }, { 'indexed': False, 'name': 'b', 'type': 'int256' }, ], 'type': 'event', }] contract_abi = ContractTranslator(event_abi) normalized_name = normalize_name('Test') encode_types = ['int256', 'int256'] id_ = event_id(normalized_name, encode_types) topics = [id_] data = encode_abi(encode_types, [1, 2]) result = contract_abi.decode_event(topics, data) assert result['_event_type'] == b'Test' assert result['a'] == 1 assert result['b'] == 2
def create_contract(path, args=(), sender=ethtester.k0, libraries=dict()): abi, hexcode = deployer.builder.get_contract_data(path) encoded_args = ( ContractTranslator(abi).encode_constructor_arguments(args) if args else b'') libraries = _encode_libs(libraries) linked_hexcode = link_code(hexcode, libraries) code = ethutils.decode_hex(linked_hexcode) + encoded_args address = ethtester.chain.tx(sender=sender, to=b'', startgas=START_GAS, data=code) return ethtester.ABIContract(ethtester.chain, abi, address)
def tester_deploy_contract(tester_state, private_key, contract_name, contract_file, constructor_parameters=None): contract_path = get_contract_path(contract_file) all_contracts = _solidity.compile_file(contract_path, libraries=dict()) contract = all_contracts[contract_name] contract_interface = contract['abi'] log.info('Deploying "{}" contract'.format(contract_file)) dependencies = deploy_dependencies_symbols(all_contracts) deployment_order = dependencies_order_of_build(contract_name, dependencies) log.info('Deploing dependencies: {}'.format(str(deployment_order))) deployment_order.pop() # remove `contract_name` from the list libraries = dict() for deploy_contract in deployment_order: dependency_contract = all_contracts[deploy_contract] hex_bytecode = _solidity.solidity_resolve_symbols( dependency_contract['bin_hex'], libraries, ) bytecode = decode_hex(hex_bytecode) dependency_contract['bin_hex'] = hex_bytecode dependency_contract['bin'] = bytecode log.info('Creating contract {}'.format(deploy_contract)) contract_address = tester_state.evm( bytecode, private_key, endowment=0, ) tester_state.mine(number_of_blocks=1) if len(tester_state.block.get_code(contract_address)) == 0: raise Exception('Contract code empty') libraries[deploy_contract] = encode_hex(contract_address) hex_bytecode = _solidity.solidity_resolve_symbols(contract['bin_hex'], libraries) bytecode = hex_bytecode.decode('hex') contract['bin_hex'] = hex_bytecode contract['bin'] = bytecode if constructor_parameters: translator = ContractTranslator(contract_interface) parameters = translator.encode_constructor_arguments(constructor_parameters) bytecode = contract['bin'] + parameters else: bytecode = contract['bin'] log.info('Creating contract {}'.format(contract_name)) contract_address = tester_state.evm( bytecode, private_key, endowment=0, ) tester_state.mine(number_of_blocks=1) if len(tester_state.block.get_code(contract_address)) == 0: raise Exception('Contract code empty') return contract_address
from ethereum import transactions as t from ethereum.abi import ContractTranslator from ethereum._solidity import get_solidity import rlp solidity = get_solidity() key = '7942db5f27595d040231a44b95de331d45eaa78cfa3f21663c95d4bbc97afbe4' addr = 'ce7fb4c38949d7c09bd95197c3981ec8bb0638e5' args, kwargs = [], {} i = 0 while i < len(sys.argv): if sys.argv[i][:2] == '--': kwargs[sys.argv[i][2:]] = sys.argv[i+1] i += 2 else: args.append(sys.argv[i]) i += 1 adStorer_abi = solidity.mk_full_signature(open('one_phase_auction.sol').read() + open('two_phase_auction.sol').read() + open('adStorer.sol').read(), contract_name='adStorer') ct = ContractTranslator(adStorer_abi) nonce = int(kwargs['nonce']) data = ct.encode('initialize', [240, 240, 240, 120, 50, 10]) o = '[' for i in range(8): tx = t.Transaction(nonce, 60 * 10**9, 2500000, kwargs['address'], 0, data) o += '"0x' + rlp.encode(tx.sign(key)).encode('hex') + '",' nonce += 1 print o[:-1] + ']'
def call_function( priv_key, value, contract_hash, contract_abi, function_name, args ): translator = ContractTranslator(contract_abi) call = translator.encode_function_call(function_name, args) return make_transaction(priv_key, contract_hash, value, call)
def deploy_solidity_contract( self, # pylint: disable=too-many-locals sender, contract_name, all_contracts, libraries, constructor_parameters, contract_path=None, timeout=None, gasprice=GAS_PRICE): """ Deploy a solidity contract. Args: sender (address): the sender address contract_name (str): the name of the contract to compile all_contracts (dict): the json dictionary containing the result of compiling a file libraries (list): A list of libraries to use in deployment constructor_parameters (tuple): A tuple of arguments to pass to the constructor contract_path (str): If we are dealing with solc >= v0.4.9 then the path to the contract is a required argument to extract the contract data from the `all_contracts` dict. timeout (int): Amount of time to poll the chain to confirm deployment gasprice: The gasprice to provide for the transaction """ if contract_name in all_contracts: contract_key = contract_name elif contract_path is not None: _, filename = os.path.split(contract_path) contract_key = filename + ':' + contract_name if contract_key not in all_contracts: raise ValueError('Unknown contract {}'.format(contract_name)) else: raise ValueError( 'Unknown contract {} and no contract_path given'.format(contract_name) ) libraries = dict(libraries) contract = all_contracts[contract_key] contract_interface = contract['abi'] symbols = solidity_unresolved_symbols(contract['bin_hex']) if symbols: available_symbols = list(map(solidity_library_symbol, all_contracts.keys())) unknown_symbols = set(symbols) - set(available_symbols) if unknown_symbols: msg = 'Cannot deploy contract, known symbols {}, unresolved symbols {}.'.format( available_symbols, unknown_symbols, ) raise Exception(msg) dependencies = deploy_dependencies_symbols(all_contracts) deployment_order = dependencies_order_of_build(contract_key, dependencies) deployment_order.pop() # remove `contract_name` from the list log.debug('Deploying dependencies: {}'.format(str(deployment_order))) for deploy_contract in deployment_order: dependency_contract = all_contracts[deploy_contract] hex_bytecode = solidity_resolve_symbols(dependency_contract['bin_hex'], libraries) bytecode = unhexlify(hex_bytecode) dependency_contract['bin_hex'] = hex_bytecode dependency_contract['bin'] = bytecode transaction_hash_hex = self.send_transaction( sender, to=b'', data=bytecode, gasprice=gasprice, ) transaction_hash = unhexlify(transaction_hash_hex) self.poll(transaction_hash, timeout=timeout) receipt = self.eth_getTransactionReceipt(transaction_hash) contract_address = receipt['contractAddress'] # remove the hexadecimal prefix 0x from the address contract_address = contract_address[2:] libraries[deploy_contract] = contract_address deployed_code = self.eth_getCode(address_decoder(contract_address)) if len(deployed_code) == 0: raise RuntimeError('Contract address has no code, check gas usage.') hex_bytecode = solidity_resolve_symbols(contract['bin_hex'], libraries) bytecode = unhexlify(hex_bytecode) contract['bin_hex'] = hex_bytecode contract['bin'] = bytecode if constructor_parameters: translator = ContractTranslator(contract_interface) parameters = translator.encode_constructor_arguments(constructor_parameters) bytecode = contract['bin'] + parameters else: bytecode = contract['bin'] transaction_hash_hex = self.send_transaction( sender, to=b'', data=bytecode, gasprice=gasprice, ) transaction_hash = unhexlify(transaction_hash_hex) self.poll(transaction_hash, timeout=timeout) receipt = self.eth_getTransactionReceipt(transaction_hash) contract_address = receipt['contractAddress'] deployed_code = self.eth_getCode(address_decoder(contract_address)) if len(deployed_code) == 0: raise RuntimeError( 'Deployment of {} failed. Contract address has no code, check gas usage.'.format( contract_name, ) ) return self.new_contract_proxy( contract_interface, contract_address, )
class EthJsonRpc(object): DEFAULT_GAS_FOR_TRANSACTIONS = 500000 DEFAULT_GAS_PRICE = 10 * 10 ** 12 # 10 szabo def __init__( self, host="localhost", port=GETH_DEFAULT_RPC_PORT, tls=False, contract_code=None, contract_address=None ): self.host = host self.port = port self.tls = tls self.contract_code = None self.signature = None self.translation = None self.contract_address = contract_address self.update_code(contract_code) self.compilers = {} try: import serpent self.compilers["serpent"] = serpent.compile self.compilers["lll"] = serpent.compile_lll except ImportError: print '[WARNING] Could not import module "serpent". Compiler will not be available.' try: import solidity self.compilers["solidity"] = solidity.compile except ImportError: try: from ethereum._solidity import solc_wrapper self.compilers["solidity"] = solc_wrapper.compile except ImportError: print '[WARNING] Could not import module "solidity" or "solc_wrapper". Compiler will not be available.' def update_code(self, contract_code): if contract_code: self.contract_code = contract_code self.signature = serpent.mk_full_signature(contract_code) self.translation = ContractTranslator(self.signature) def _call(self, method, params=None, _id=0): params = params or [] data = json.dumps({"jsonrpc": "2.0", "method": method, "params": params, "id": _id}) scheme = "http" if self.tls: scheme += "s" url = "{}://{}:{}".format(scheme, self.host, self.port) response = requests.post(url, data=data).json() if "result" in response: return response["result"] else: raise RuntimeError("Error from RPC call. Returned payload: {0}".format(response)) def _encode_function(self, signature, param_values): prefix = utils.big_endian_to_int(utils.sha3(signature)[:4]) if signature.find("(") == -1: raise RuntimeError('Invalid function signature. Missing "(" and/or ")"...') if signature.find(")") - signature.find("(") == 1: return utils.encode_int(prefix) types = signature[signature.find("(") + 1 : signature.find(")")].split(",") encoded_params = encode_abi(types, param_values) return utils.zpad(utils.encode_int(prefix), 4) + encoded_params def _install_contract(self, language, contract_code, value=0, from_address=None, gas=None, gas_price=None): byte_code = self.compilers[language](contract_code) return self.eth_sendTransaction( data=byte_code, value=value, from_address=from_address, gas=gas, gas_price=gas_price ) def install_solidity_contract(self, contract_code, value=0, from_address=None, gas=None, gas_price=None): """ Installs a solidity contract into ethereum node """ return self._install_contract("solidity", contract_code, value, from_address, gas, gas_price) def install_serpent_contract(self, contract_code, value=0, from_address=None, gas=None, gas_price=None): """ Installs a serpent contract into ethereum node """ return self._install_contract("serpent", contract_code, value, from_address, gas, gas_price) def install_lll_contract(self, contract_code, value=0, from_address=None, gas=None, gas_price=None): """ Installs a lll contract into ethereum node """ return self._install_contract("lll", contract_code, value, from_address, gas, gas_price) def contract_instant_call( self, to_address, function_signature, function_parameters=None, result_types=None, default_block=BLOCK_TAG_LATEST, ): """ This method makes a instant call on a contract function without the need to have the contract source code. Examples of function_signature in solidity: mult(uint x, uint y) => sig: mult(uint256,uint256) (all uint should be transformed to uint256) setAddress(address entity_address) => sig:setAddress(address) doSomething() => sig: doSomething() (functions with no parameters must end with the '()') In serpent, all functions parameter signatures are int256. Example: setXYZ(x, y, z) => sig: setXYZ(int256,int256,int256) """ data = self._encode_function(function_signature, function_parameters) params = [{"to": to_address, "data": "0x{0}".format(data.encode("hex"))}, default_block] response = self._call("eth_call", params) return decode_abi(result_types, response[2:].decode("hex")) def contract_transaction_call( self, to_address, function_signature, function_parameters=None, from_address=None, gas=None, gas_price=None, default_block=BLOCK_TAG_LATEST, ): """ This method makes a call on a contract function through a transaction. Returns the transaction_id. Examples of function_signature in solidity: mult(uint x, uint y) => sig: mult(uint256,uint256) (all uint should be transformed to uint256) setAddress(address entity_address) => sig:setAddress(address) doSomething() => sig: doSomething() (functions with no parameters must end with the '()') In serpent, all functions parameter signatures are int256. Example: setXYZ(x, y, z) => sig: setXYZ(int256,int256,int256) """ # Default values for gas and gas_price gas = gas or self.DEFAULT_GAS_FOR_TRANSACTIONS gas_price = gas_price or self.DEFAULT_GAS_PRICE # Default value for from_address from_address = from_address or self.eth_accounts()[0] data = self._encode_function(function_signature, function_parameters) params = { "from": from_address, "to": to_address, "gas": "0x{0:x}".format(gas), "gasPrice": "0x{0:x}".format(gas_price), "value": None, "data": "0x{0}".format(data.encode("hex")) if data else None, } response = self._call("eth_sendTransaction", [params]) return response def create_contract(self, contract_code, value=0, from_address=None, gas=None, gas_price=None): self.update_code(contract_code) byte_code = serpent.compile(contract_code) self.contract_address = self.eth_sendTransaction( data=byte_code, value=value, from_address=from_address, gas=gas, gas_price=gas_price ) return self.contract_address ################################################################################ def web3_clientVersion(self): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#web3_clientversion TESTED """ return self._call("web3_clientVersion") def web3_sha3(self, data): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#web3_sha3 """ data = str(data).encode("hex") return self._call("web3_sha3", [data]) def net_version(self): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#net_version TESTED """ return self._call("net_version") def net_peerCount(self): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#net_peercount TESTED """ return hex_to_int(self._call("net_peerCount")) def net_listening(self): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#net_listening TESTED """ return self._call("net_listening") def eth_protocolVersion(self): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_protocolversion TESTED """ return self._call("eth_protocolVersion") def eth_coinbase(self): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_coinbase TESTED """ return self._call("eth_coinbase") def eth_mining(self): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_mining TESTED """ return self._call("eth_mining") def eth_hashrate(self): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_hashrate TESTED """ return hex_to_int(self._call("eth_hashrate")) def eth_gasPrice(self): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_gasprice TESTED """ return hex_to_int(self._call("eth_gasPrice")) def eth_accounts(self): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_accounts TESTED """ return self._call("eth_accounts") def eth_blockNumber(self): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_blocknumber TESTED """ return hex_to_int(self._call("eth_blockNumber")) def eth_getBalance(self, address=None, default_block=BLOCK_TAG_LATEST): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getbalance """ if isinstance(default_block, basestring): if default_block not in BLOCK_TAGS: raise ValueError address = address or self.eth_coinbase() return self._call("eth_getBalance", [address, default_block]) def eth_getStorageAt(self, address, position, default_block=BLOCK_TAG_LATEST): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getstorageat """ if isinstance(default_block, basestring): if default_block not in BLOCK_TAGS: raise ValueError return self._call("eth_getStorageAt", [address, hex(position), default_block]) def eth_getTransactionCount(self, address, block=BLOCK_TAG_LATEST): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_gettransactioncount TESTED """ block = validate_block(block) return hex_to_int(self._call("eth_getTransactionCount", [address, block])) def eth_getBlockTransactionCountByHash(self, block_hash): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getblocktransactioncountbyhash TESTED """ return hex_to_int(self._call("eth_getBlockTransactionCountByHash", [block_hash])) def eth_getBlockTransactionCountByNumber(self, block=BLOCK_TAG_LATEST): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getblocktransactioncountbynumber TESTED """ block = validate_block(block) return hex_to_int(self._call("eth_getBlockTransactionCountByNumber", [block])) def eth_getUncleCountByBlockHash(self, block_hash): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getunclecountbyblockhash TESTED """ return hex_to_int(self._call("eth_getUncleCountByBlockHash", [block_hash])) def eth_getUncleCountByBlockNumber(self, block=BLOCK_TAG_LATEST): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getunclecountbyblocknumber TESTED """ block = validate_block(block) return hex_to_int(self._call("eth_getUncleCountByBlockNumber", [block])) def eth_getCode(self, address, default_block=BLOCK_TAG_LATEST): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getcode """ if isinstance(default_block, basestring): if default_block not in BLOCK_TAGS: raise ValueError return self._call("eth_getCode", [address, default_block]) def eth_sign(self, address, data): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign """ return self._call("eth_sign", [address, data]) def eth_sendTransaction( self, to_address=None, function_name=None, data=None, value=0, from_address=None, gas=None, gas_price=None ): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sendtransaction """ # Default values for gas and gas_price gas = gas or self.DEFAULT_GAS_FOR_TRANSACTIONS gas_price = gas_price or self.DEFAULT_GAS_PRICE # Default value for from_address from_address = from_address or self.eth_accounts()[0] if function_name: if data is None: data = [] data = self.translation.encode(function_name, data) params = { "from": from_address, "to": to_address, "gas": "0x{0:x}".format(gas), "gasPrice": "0x{0:x}".format(gas_price), "value": "0x{0:x}".format(value) if value else None, "data": "0x{0}".format(data.encode("hex")) if data else None, } return self._call("eth_sendTransaction", [params]) def eth_call(self, to_address, function_name, data=None, code=None, default_block=BLOCK_TAG_LATEST): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_call """ if isinstance(default_block, basestring): if default_block not in BLOCK_TAGS: raise ValueError data = data or [] data = self.translation.encode(function_name, data) params = [{"to": to_address, "data": "0x{0}".format(data.encode("hex"))}, default_block] response = self._call("eth_call", params) if function_name: response = self.translation.decode(function_name, response[2:].decode("hex")) return response def eth_estimateGas(self): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_estimategas """ return self._call("eth_estimateGas") def eth_getBlockByHash(self, block_hash, tx_objects=True): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getblockbyhash TESTED """ return self._call("eth_getBlockByHash", [block_hash, tx_objects]) def eth_getBlockByNumber(self, block=BLOCK_TAG_LATEST, tx_objects=True): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getblockbynumber TESTED """ block = validate_block(block) return self._call("eth_getBlockByNumber", [block, tx_objects]) def eth_getTransactionByHash(self, tx_hash): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_gettransactionbyhash TESTED """ return self._call("eth_getTransactionByHash", [tx_hash]) def eth_getTransactionByBlockHashAndIndex(self, block_hash, index): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_gettransactionbyblockhashandindex """ return self._call("eth_getTransactionByBlockHashAndIndex", [block_hash, hex(index)]) def eth_getTransactionByBlockNumberAndIndex(self, block_number, index): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_gettransactionbyblocknumberandindex """ return self._call("eth_getTransactionByBlockNumberAndIndex", [block_number, hex(index)]) def eth_getTransactionReceipt(self, tx_hash): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_gettransactionreceipt """ return self._call("eth_getTransactionReceipt", [tx_hash]) def eth_getUncleByBlockHashAndIndex(self, block_hash, index, transaction_objects=True): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getunclebyblockhashandindex """ return self._call("eth_getUncleByBlockHashAndIndex", [block_hash, hex(index), transaction_objects]) def eth_getUncleByBlockNumberAndIndex(self, block_number, index, transaction_objects=True): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getunclebyblocknumberandindex """ return self._call("eth_getUncleByBlockNumberAndIndex", [block_number, hex(index), transaction_objects]) def eth_getCompilers(self): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getcompilers TESTED """ return self._call("eth_getCompilers") def eth_compileLLL(self, code): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_compilelll """ return self._call("eth_compileLLL", [code]) def eth_compileSolidity(self, code): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_compilesolidity """ return self._call("eth_compileSolidity", [code]) def eth_compileSerpent(self, code): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_compileserpent """ return self._call("eth_compileSerpent", [code]) def eth_newFilter(self, from_block=BLOCK_TAG_LATEST, to_block=BLOCK_TAG_LATEST, address=None, topics=None): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_newfilter """ _filter = {"fromBlock": from_block, "toBlock": to_block, "address": address, "topics": topics} return self._call("eth_newFilter", [_filter]) def eth_newBlockFilter(self, default_block=BLOCK_TAG_LATEST): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_newblockfilter """ return self._call("eth_newBlockFilter", [default_block]) def eth_newPendingTransactionFilter(self): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_newpendingtransactionfilter TESTED """ return hex_to_int(self._call("eth_newPendingTransactionFilter")) def eth_uninstallFilter(self, filter_id): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_uninstallfilter """ return self._call("eth_uninstallFilter", [filter_id]) def eth_getFilterChanges(self, filter_id): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getfilterchanges """ return self._call("eth_getFilterChanges", [filter_id]) def eth_getFilterLogs(self, filter_id): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getfilterlogs """ return self._call("eth_getFilterLogs", [filter_id]) def eth_getLogs(self, filter_object): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getlogs """ return self._call("eth_getLogs", [filter_object]) def eth_getWork(self): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getwork TESTED """ return self._call("eth_getWork") def eth_submitWork(self, nonce, header, mix_digest): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_submitwork """ return self._call("eth_submitWork", [nonce, header, mix_digest]) def eth_submitHashrate(self, hash_rate, client_id): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_submithashrate """ return self._call("eth_submitHashrate", [hash_rate, client_id]) def db_putString(self, db_name, key, value): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#db_putstring TESTED """ warnings.warn("deprecated", DeprecationWarning) return self._call("db_putString", [db_name, key, value]) def db_getString(self, db_name, key): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#db_getstring TESTED """ warnings.warn("deprecated", DeprecationWarning) return self._call("db_getString", [db_name, key]) def db_putHex(self, db_name, key, value): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#db_puthex TESTED """ if not value.startswith("0x"): value = "0x{}".format(value) warnings.warn("deprecated", DeprecationWarning) return self._call("db_putHex", [db_name, key, value]) def db_getHex(self, db_name, key): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#db_gethex TESTED """ warnings.warn("deprecated", DeprecationWarning) return self._call("db_getHex", [db_name, key]) def shh_post(self, topics, payload, priority, ttl, _from=None, to=None): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_post """ whisper_object = { "from": _from, "to": to, "topics": topics, "payload": payload, "priority": hex(priority), "ttl": hex(ttl), } return self._call("shh_post", [whisper_object]) def shh_version(self): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_version N/A """ return self._call("shh_version") def shh_newIdentity(self): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_newidentity N/A """ return self._call("shh_newIdentity") def shh_hasIdentity(self, address): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_hasidentity """ return self._call("shh_hasIdentity", [address]) def shh_newGroup(self): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_newgroup N/A """ return self._call("shh_newGroup") def shh_addToGroup(self): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_addtogroup """ return self._call("shh_addToGroup") def shh_newFilter(self, to, topics): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_newfilter """ _filter = {"to": to, "topics": topics} return self._call("shh_newFilter", [_filter]) def shh_uninstallFilter(self, filter_id): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_uninstallfilter """ return self._call("shh_uninstallFilter", [filter_id]) def shh_getFilterChanges(self, filter_id): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_getfilterchanges """ return self._call("shh_getFilterChanges", [filter_id]) def shh_getMessages(self, filter_id): """ https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_getmessages """ return self._call("shh_getMessages", [filter_id])
def update_code(self, contract_code): if contract_code: self.contract_code = contract_code self.signature = serpent.mk_full_signature(contract_code) self.translation = ContractTranslator(self.signature)
def tester_deploy_contract( tester_chain, private_key, contract_name, contract_path, constructor_parameters=None): all_contracts = _solidity.compile_file(contract_path, libraries=dict()) contract_key = solidity_get_contract_key(all_contracts, contract_path, contract_name) contract = all_contracts[contract_key] contract_interface = contract['abi'] log.info('Deploying "{}" contract'.format(os.path.basename(contract_path))) dependencies = deploy_dependencies_symbols(all_contracts) deployment_order = dependencies_order_of_build(contract_key, dependencies) log.info('Deploying dependencies: {}'.format(str(deployment_order))) deployment_order.pop() # remove `contract_name` from the list libraries = dict() for deploy_contract in deployment_order: dependency_contract = all_contracts[deploy_contract] hex_bytecode = _solidity.solidity_resolve_symbols( dependency_contract['bin_hex'], libraries, ) bytecode = unhexlify(hex_bytecode) dependency_contract['bin_hex'] = hex_bytecode dependency_contract['bin'] = bytecode log.info('Creating contract {}'.format(deploy_contract)) contract_address = tester_chain.contract(bytecode, language='evm', sender=private_key) tester_chain.mine(number_of_blocks=1) if len(tester_chain.head_state.get_code(contract_address)) == 0: raise Exception('Contract code empty') libraries[deploy_contract] = encode_hex(contract_address) hex_bytecode = _solidity.solidity_resolve_symbols(contract['bin_hex'], libraries) bytecode = unhexlify(hex_bytecode) contract['bin_hex'] = hex_bytecode contract['bin'] = bytecode if constructor_parameters: translator = ContractTranslator(contract_interface) parameters = translator.encode_constructor_arguments(constructor_parameters) bytecode = contract['bin'] + parameters else: bytecode = contract['bin'] log.info('Creating contract {}'.format(contract_name)) contract_address = tester_chain.contract(bytecode, language='evm', sender=private_key) tester_chain.mine(number_of_blocks=1) if len(tester_chain.head_state.get_code(contract_address)) == 0: raise Exception('Contract code empty') return contract_address
def event_decoder(event: Log, contract_translator: ContractTranslator): return contract_translator.decode_event(event.topics, event.data)
class EthJsonRpc: def __init__(self, host, port, contract_code=None, contract_address=None): self.host = host self.port = port self.contract_code = None self.signature = None self.translation = None self.contract_address = contract_address self.update_code(contract_code) def update_code(self, contract_code): if contract_code: self.contract_code = contract_code self.signature = serpent.mk_full_signature(contract_code) self.translation = ContractTranslator(self.signature) def _call(self, method, params=None, _id=0): if params is None: params = [] data = json.dumps({ 'jsonrpc': '2.0', 'method': method, 'params': params, 'id': _id }) response = requests.post("http://{}:{}".format(self.host, self.port), data=data).json() return response def create_contract(self, contract_code, value=0, from_address=None, gas=0, gas_price=0): self.update_code(contract_code) byte_code = serpent.compile(contract_code) self.contract_address = self.eth_sendTransaction(data=byte_code, value=value, from_address=from_address, gas=gas, gas_price=gas_price) return self.contract_address def eth_sendTransaction(self, to_address=None, function_name=None, data=None, value=0, from_address=None, gas=0, gas_price=0, code=None): """ Creates new message call transaction or a contract creation, if the data field contains code. """ if code: self.update_code(code) else: self.update_code(self.eth_getCode(to_address)) if function_name: if data is None: data = [] data = self.translation.encode(function_name, data) params = { 'from': from_address, 'to': to_address, 'gas': hex(gas) if gas else None, 'gasPrice': hex(gas_price) if gas_price else None, 'value': hex(value) if value else None, 'data': '0x{}'.format(data.encode('hex')) if data else None } return self._call('eth_sendTransaction', [params]) def eth_call(self, to_address, function_name, data=None, code=None, default_block="latest"): """ Executes a new message call immediately without creating a transaction on the block chain. """ if code: self.update_code(code) else: self.update_code(self.eth_getCode(to_address)) if data is None: data = [] data = self.translation.encode(function_name, data) params = [ { 'to': to_address, 'data': '0x{}'.format(data.encode('hex')) }, default_block ] response = self._call('eth_call', params) if function_name: response = self.translation.decode(function_name, response[2:].decode('hex')) return response def web3_clientVersion(self): """ Returns the current client version. """ return self._call('web3_clientVersion') def web3_sha3(self, data): """ Returns SHA3 of the given data. """ data = str(data).encode('hex') return self._call('web3_sha3', [data]) def net_version(self): """ Returns the current network protocol version. """ return self._call('net_version') def net_listening(self): """ Returns true if client is actively listening for network connections. """ return self._call('net_listening') def net_peerCount(self): """ Returns number of peers currenly connected to the client. """ return self._call('net_peerCount') def eth_version(self): """ Returns the current ethereum protocol version. """ return self._call('eth_version') def eth_coinbase(self): """ Returns the client coinbase address. """ return self._call('eth_coinbase') def eth_mining(self): """ Returns true if client is actively mining new blocks. """ return self._call('eth_mining') def eth_gasPrice(self): """ Returns the current price per gas in wei. """ return self._call('eth_gasPrice') def eth_accounts(self): """ Returns a list of addresses owned by client. """ return self._call('eth_accounts') def eth_blockNumber(self): """ Returns the number of most recent block. """ return self._call('eth_blockNumber') def eth_getBalance(self, address, default_block="latest"): """ Returns the balance of the account of given address. """ return self._call('eth_getBalance', [address, default_block]) def eth_getStorageAt(self, address, position, default_block="latest"): """ Returns the value from a storage position at a given address. """ return self._call('eth_getStorageAt', [address, hex(position), default_block]) def eth_getTransactionCount(self, address, default_block="latest"): """ Returns the number of transactions send from a address. """ return self._call('eth_getTransactionCount', [address, default_block]) def eth_getBlockTransactionCountByHash(self, block_hash): """ Returns the number of transactions in a block from a block matching the given block hash. """ return self._call('eth_getTransactionCount', [block_hash]) def eth_getBlockTransactionCountByNumber(self, block_number): """ Returns the number of transactions in a block from a block matching the given block number. """ return self._call('eth_getBlockTransactionCountByNumber', [hex(block_number)]) def eth_getUncleCountByblockHash(self, block_hash): """ Returns the number of uncles in a block from a block matching the given block hash. """ return self._call('eth_getUncleCountByblockHash', [block_hash]) def eth_getUncleCountByblockNumber(self, block_number): """ Returns the number of uncles in a block from a block matching the given block number. """ return self._call('eth_getUncleCountByblockNumber', [hex(block_number)]) def eth_getCode(self, address, default_block="latest"): """ Returns code at a given address. """ return self._call('eth_getCode', [address, default_block]) def eth_getBlockByHash(self, block_hash, transaction_objects=True): """ Returns information about a block by hash. """ return self._call('eth_getBlockByHash', [block_hash, transaction_objects]) def eth_flush(self): """ """ return self._call('eth_flush') def eth_getBlockByNumber(self, block_number, transaction_objects=True): """ Returns information about a block by hash. """ return self._call('eth_getBlockByNumber', [block_number, transaction_objects]) def eth_getTransactionByHash(self, transaction_hash): """ Returns the information about a transaction requested by transaction hash. """ return self._call('eth_getTransactionByHash', [transaction_hash]) def eth_getTransactionByblockHashAndIndex(self, block_hash, index): """ Returns information about a transaction by block hash and transaction index position. """ return self._call('eth_getTransactionByblock_hashAndIndex', [block_hash, hex(index)]) def eth_getTransactionByblockNumberAndIndex(self, block_number, index): """ Returns information about a transaction by block number and transaction index position. """ return self._call('eth_getTransactionByblock_numberAndIndex', [block_number, hex(index)]) def eth_getUncleByblockHashAndIndex(self, block_hash, index, transaction_objects=True): """ Returns information about a uncle of a block by hash and uncle index position. """ return self._call('eth_getUncleByblock_hashAndIndex', [block_hash, hex(index), transaction_objects]) def eth_getUncleByblockNumberAndIndex(self, block_number, index, transaction_objects=True): """ Returns information about a uncle of a block by number and uncle index position. """ return self._call('eth_getUncleByblock_numberAndIndex', [block_number, hex(index), transaction_objects]) def eth_getCompilers(self): """ Returns a list of available compilers in the client. """ return self._call('eth_getCompilers') def eth_compileSolidity(self, code): """ Returns compiled solidity code. """ return self._call('eth_compileSolidity', [code]) def eth_compileLLL(self, code): """ Returns compiled LLL code. """ return self._call('eth_compileLLL', [code]) def eth_compileSerpent(self, code): """ Returns compiled serpent code. """ return self._call('eth_compileSerpent', [code]) def eth_newFilter(self, from_block="latest", to_block="latest", address=None, topics=None): """ Creates a filter object, based on filter options, to notify when the state changes (logs). To check if the state has changed, call eth_getFilterChanges. """ _filter = { 'fromBlock': from_block, 'toBlock': to_block, 'address': address, 'topics': topics } return self._call('eth_newFilter', [_filter]) def eth_newBlockFilter(self, default_block="latest"): """ Creates a filter object, based on an option string, to notify when state changes (logs). To check if the state has changed, call eth_getFilterChanges. """ return self._call('eth_newBlockFilter', [default_block]) def eth_uninstallFilter(self, filter_id): """ Uninstalls a filter with given id. Should always be called when watch is no longer needed. Additonally Filters timeout when they aren't requested with eth_getFilterChanges for a period of time. """ return self._call('eth_uninstallFilter', [hex(filter_id)]) def eth_getFilterChanges(self, filter_id): """ Polling method for a filter, which returns an array of logs which occurred since last poll. """ return self._call('eth_getFilterChanges', [hex(filter_id)]) def eth_getFilterLogs(self, filter_id): """ Returns an array of all logs matching filter with given id. """ return self._call('eth_getFilterLogs', [hex(filter_id)]) def eth_getLogs(self, filter_object): """ Returns an array of all logs matching a given filter object. """ return self._call('eth_getLogs', [filter_object]) def eth_getWork(self): """ Returns the hash of the current block, the seedHash, and the difficulty to be met. """ return self._call('eth_getWork') def eth_submitWork(self, nonce, header, mix_digest): """ Used for submitting a proof-of-work solution. """ return self._call('eth_submitWork', [nonce, header, mix_digest]) def db_putString(self, database_name, key_name, string): """ Stores a string in the local database. """ return self._call('db_putString', [database_name, key_name, string]) def db_getString(self, database_name, key_name): """ Stores a string in the local database. """ return self._call('db_getString', [database_name, key_name]) def db_putHex(self, database_name, key_name, string): """ Stores binary data in the local database. """ return self._call('db_putHex', [database_name, key_name, string.encode('hex')]) def db_getHex(self, database_name, key_name): """ Returns binary data from the local database. """ return self._call('db_getString', [database_name, key_name]).decode('hex') def shh_version(self): """ Returns the current whisper protocol version. """ return self._call('shh_version') def shh_post(self, topics, payload, priority, ttl, _from=None, to=None): """ Sends a whisper message. """ whisper_object = { 'from': _from, 'to': to, 'topics': topics, 'payload': payload, 'priority': priority, 'ttl': ttl } return self._call('shh_post', [whisper_object]) def shh_newIdentinty(self): """ Creates new whisper identity in the client. """ return self._call('shh_newIdentinty') def shh_hasIdentity(self, address): """ Checks if the client hold the private keys for a given identity. """ return self._call('shh_hasIdentity', [address]) def shh_newGroup(self): """ """ return self._call('shh_hasIdentity') def shh_addToGroup(self): """ """ return self._call('shh_addToGroup') def shh_newFilter(self, to, topics): """ Creates filter to notify, when client receives whisper message matching the filter options. """ _filter = { 'to': to, 'topics': topics } return self._call('shh_newFilter', [_filter]) def shh_uninstallFilter(self, filter_id): """ Uninstalls a filter with given id. Should always be called when watch is no longer needed. Additonally Filters timeout when they aren't requested with shh_getFilterChanges for a period of time. """ return self._call('shh_uninstallFilter', [hex(filter_id)]) def shh_getFilterChanges(self, filter_id): """ Polling method for whisper filters. """ return self._call('shh_getFilterChanges', [hex(filter_id)]) def shh_getMessages(self, filter_id): """ Get all messages matching a filter, which are still existing in the node. """ return self._call('shh_getMessages', [hex(filter_id)])