def signup(username, password) -> Tuple[Enterprise, Signer_Impl]: try: signer = create_account(username, password) enterprise = Enterprise(username=username, password=password) contract_addr = deploy_contract("Enterprise", signer=signer) enterprise.contract_addr = contract_addr enterprise.account_addr = str(signer.keypair.address) enterprise.account_pub = str(signer.keypair.public_key) enterprise.account_priv = str(signer.keypair.private_key) privkey, pubkey = gen_rsakey() enterprise.envelope_pub = pubkey enterprise.envelope_priv = privkey managementAddr = db.session.query(Contracts).filter( Contracts.name == "Management").first().addr call_contract(managementAddr, "Management", "addEnterprise", args=[ username, to_checksum_address(enterprise.account_addr), to_checksum_address(enterprise.contract_addr), enterprise.envelope_pub, "" ]) db.session.add(enterprise) db.session.commit() except Exception: traceback.print_exc() db.session.rollback() return None, None return enterprise, signer
def _handle_pooltogether(normalized_balance: FVal, token_name: str) -> Optional[DefiBalance]: """Special handling for pooltogether https://github.com/rotki/rotki/issues/1429 """ if 'DAI' in token_name: dai_price = Inquirer.find_usd_price(A_DAI) return DefiBalance( token_address=to_checksum_address( '0x49d716DFe60b37379010A75329ae09428f17118d'), token_name='Pool Together DAI token', token_symbol='plDAI', balance=Balance( amount=normalized_balance, usd_value=normalized_balance * dai_price, ), ) if 'USDC' in token_name: usdc_price = Inquirer.find_usd_price(A_USDC) return DefiBalance( token_address=to_checksum_address( '0xBD87447F48ad729C5c4b8bcb503e1395F62e8B98'), token_name='Pool Together USDC token', token_symbol='plUSDC', balance=Balance( amount=normalized_balance, usd_value=normalized_balance * usdc_price, ), ) # else return None
def _ens_lookup(self, web3: Optional[Web3], name: str) -> Optional[ChecksumEthAddress]: """Performs an ENS lookup and returns address if found else None May raise: - RemoteError if Etherscan is used and there is a problem querying it or parsing its response """ if web3 is not None: return web3.ens.resolve(name) # else we gotta manually query contracts via etherscan normal_name = normalize_name(name) resolver_addr = self._call_contract_etherscan( ENS_MAINNET_ADDR, abi=ENS_ABI, method_name='resolver', arguments=[normal_name_to_hash(normal_name)], ) if is_none_or_zero_address(resolver_addr): return None address = self._call_contract_etherscan( to_checksum_address(resolver_addr), abi=ENS_RESOLVER_ABI, method_name='addr', arguments=[normal_name_to_hash(normal_name)], ) if is_none_or_zero_address(address): return None return to_checksum_address(address)
def deserialize_transaction_from_etherscan( data: Dict[str, Any], internal: bool, ) -> EthereumTransaction: """Reads dict data of a transaction from etherscan and deserializes it Can raise DeserializationError if something is wrong """ try: # internal tx list contains no gasprice gas_price = -1 if internal else read_integer(data, 'gasPrice') tx_hash = read_hash(data, 'hash') input_data = read_hash(data, 'input') timestamp = deserialize_timestamp(data['timeStamp']) block_number = read_integer(data, 'blockNumber') nonce = -1 if internal else read_integer(data, 'nonce') return EthereumTransaction( timestamp=timestamp, block_number=block_number, tx_hash=tx_hash, from_address=to_checksum_address(data['from']), to_address=to_checksum_address(data['to']) if data['to'] != '' else None, value=read_integer(data, 'value'), gas=read_integer(data, 'gas'), gas_price=gas_price, gas_used=read_integer(data, 'gasUsed'), input_data=input_data, nonce=nonce, ) except KeyError as e: raise DeserializationError(f'Etherscan ethereum transaction missing expected key {str(e)}')
def pairs_and_token_details_from_graph() -> Dict[str, Any]: """Detect the uniswap v2 pool tokens by using the subgraph""" step = 1000 querystr = """ pairs(first:$first, skip: $skip) { id token0{ id symbol name decimals } token1{ id symbol name decimals } } } """ param_types = {'$first': 'Int!', '$skip': 'Int!'} param_values = {'first': step, 'skip': 0} graph = Graph('https://api.thegraph.com/subgraphs/name/uniswap/uniswap-v2') contracts = [] total_pairs_num = 0 while True: print( f'Querying graph pairs batch {param_values["skip"]} - {param_values["skip"] + step}' ) result = graph.query(querystr, param_types=param_types, param_values=param_values) for entry in result['pairs']: contracts.append({ 'address': to_checksum_address(entry['id']), 'token0': { 'address': to_checksum_address(entry['token0']['id']), 'name': entry['token0']['name'], 'symbol': entry['token0']['symbol'], 'decimals': int(entry['token0']['decimals']), }, 'token1': { 'address': to_checksum_address(entry['token1']['id']), 'name': entry['token1']['name'], 'symbol': entry['token1']['symbol'], 'decimals': int(entry['token1']['decimals']), }, }) pairs_num = len(result['pairs']) total_pairs_num += pairs_num if pairs_num < step: break param_values['skip'] = total_pairs_num return contracts
def _ens_lookup( self, web3: Optional[Web3], name: str, blockchain: SupportedBlockchain = SupportedBlockchain.ETHEREUM, ) -> Optional[Union[ChecksumEthAddress, HexStr]]: """Performs an ENS lookup and returns address if found else None TODO: currently web3.py 5.15.0 does not support multichain ENS domains (EIP-2304), therefore requesting a non-Ethereum address won't use the web3 ens library and will require to extend the library resolver ABI. An issue in their repo (#1839) reporting the lack of support has been created. This function will require refactoring once they include support for EIP-2304. https://github.com/ethereum/web3.py/issues/1839 May raise: - RemoteError if Etherscan is used and there is a problem querying it or parsing its response """ normal_name = normalize_name(name) resolver_addr = self._call_contract( web3=web3, contract_address=ENS_MAINNET_ADDR, abi=ENS_ABI, method_name='resolver', arguments=[normal_name_to_hash(normal_name)], ) if is_none_or_zero_address(resolver_addr): return None ens_resolver_abi = ENS_RESOLVER_ABI.copy() arguments = [normal_name_to_hash(normal_name)] if blockchain != SupportedBlockchain.ETHEREUM: ens_resolver_abi.extend(ENS_RESOLVER_ABI_MULTICHAIN_ADDRESS) arguments.append(blockchain.ens_coin_type()) address = self._call_contract( web3=web3, contract_address=to_checksum_address(resolver_addr), abi=ens_resolver_abi, method_name='addr', arguments=arguments, ) if is_none_or_zero_address(address): return None if blockchain != SupportedBlockchain.ETHEREUM: return HexStr(address.hex()) return to_checksum_address(address)
def _run(self): self.running = True pfs_url = get_random_pfs( service_registry=self.service_registry, block_identifier=BLOCK_ID_LATEST, pathfinding_max_fee=math.inf, ) if pfs_url is None: self.running = False log.warning( "Could not get a PFS from ServiceRegistry %s. Disabling presence monitoring.", to_checksum_address(self.service_registry.address), ) return log.info("Presence service started, PFS: %s", pfs_url) log.info("Presence polling interval: %ss", self.poll_interval) while self.running: try: response = requests.get(f"{pfs_url}/api/v1/online_addresses") response.raise_for_status() self.update_presence(response.json()) gevent.sleep(self.poll_interval) except (ConnectionError, HTTPError, Timeout): log.warning( "Error while trying to request from the PFS. Retrying in %d seconds.", self.error_poll_interval, ) gevent.sleep(self.error_poll_interval) log.info("Stopped presence service")
def get_all_active_stakers( self, periods: int, pagination_size: int = None) -> Tuple[int, List[str]]: """Only stakers which confirmed the current period (in the previous period) are used.""" if not periods > 0: raise ValueError("Period must be > 0") if pagination_size is None: pagination_size = StakingEscrowAgent.DEFAULT_PAGINATION_SIZE if self.blockchain.is_light else 0 elif pagination_size < 0: raise ValueError("Pagination size must be >= 0") if pagination_size > 0: num_stakers = self.get_staker_population() start_index = 0 n_tokens = 0 stakers = list() while start_index < num_stakers: temp_locked_tokens, temp_stakers = \ self.contract.functions.getActiveStakers(periods, start_index, pagination_size).call() n_tokens += temp_locked_tokens stakers += temp_stakers start_index += pagination_size else: n_tokens, stakers = self.contract.functions.getActiveStakers( periods, 0, 0).call() # Sanitize output of getActiveStakers: stakers' addresses are returned as uint256, but we need addresses for i in range(len(stakers)): stakers[i][0] = to_checksum_address(stakers[i][0].to_bytes( ETH_ADDRESS_BYTE_LENGTH, 'big')) return n_tokens, stakers
async def lnd_helper(mocker): contract_addr = await create_lnd_contract() mocker.patch( 'moonwalking.blocks.eth_generic.EthereumGeneric.get_contract_addr', lambda self: to_checksum_address(contract_addr), ) yield lnd_helper
def test_mint_correctly_calculates_amount_to_mint(self, mock_request, contract_instance): contract_instance = self.setup_instance_with_balance( contract_instance, 100) contract_instance._address = "0x12ae66cdc592e10b60f9097a7b0d3c59fce29876" expected_amount = contract_instance.config.token.max_funding - 100 expected_params = { "client_id": "the_client_id", "gas_limit": contract_instance.config.gas_limit, "amount": expected_amount, "target_address": "the_address", "contract_address": to_checksum_address("0x12ae66cdc592e10b60f9097a7b0d3c59fce29876"), } with pytest.raises(Sentinel): contract_instance.mint("the_address") mock_request.assert_called_once_with("spaas://rpc/contract/mint", json=expected_params)
def _get_single_balance( self, entry: Tuple[Tuple[str, str, str, int], int]) -> DefiBalance: metadata = entry[0] balance_value = entry[1] decimals = metadata[3] normalized_value = token_normalized_value(balance_value, decimals) token_symbol = metadata[2] try: asset = Asset(token_symbol) usd_price = Inquirer().find_usd_price(asset) except (UnknownAsset, UnsupportedAsset): if not _is_symbol_non_standard(token_symbol): self.msg_aggregator.add_error( f'Unsupported asset {token_symbol} encountered during DeFi protocol queries', ) usd_price = Price(ZERO) usd_value = normalized_value * usd_price defi_balance = DefiBalance( token_address=to_checksum_address(metadata[0]), token_name=metadata[1], token_symbol=token_symbol, balance=Balance(amount=normalized_value, usd_value=usd_value), ) return defi_balance
def signup(username, password) -> Tuple[Audit, Signer_Impl]: try: signer = create_account(username, password) audit = Audit(username=username, password=password) audit.account_addr = str(signer.keypair.address) audit.account_pub = str(signer.keypair.public_key) audit.account_priv = str(signer.keypair.private_key) privkey, pubkey = gen_rsakey() audit.envelope_pub = pubkey audit.envelope_priv = privkey managementAddr = db.session.query(Contracts).filter( Contracts.name == "Management").first().addr call_contract(managementAddr, "Management", "addAudit", args=[ username, to_checksum_address(audit.account_addr), audit.envelope_pub, "" ], signer=signer) db.session.add(audit) db.session.commit() except Exception: traceback.print_exc() db.session.rollback() return None, None return audit, signer
def handle_protocols( self, protocol_name: str, token_symbol: str, normalized_balance: FVal, token_address: str, token_name: str, ) -> Optional[DefiBalance]: """Special handling for price for token/protocols which are easier to do onchain or need some kind of special treatment. """ if protocol_name == 'PoolTogether': result = _handle_pooltogether(normalized_balance, token_name) if result is not None: return result underlying_asset_price = get_underlying_asset_price(token_symbol) usd_price = handle_defi_price_query(self.ethereum, token_symbol, underlying_asset_price) if usd_price is None: return None return DefiBalance( token_address=to_checksum_address(token_address), token_name=token_name, token_symbol=token_symbol, balance=Balance(amount=normalized_balance, usd_value=normalized_balance * usd_price), )
def __init__( self, blockchain_accounts: BlockchainAccounts, owned_eth_tokens: List[EthereumToken], ethchain: 'Ethchain', msg_aggregator: MessagesAggregator, ): self.ethchain = ethchain self.msg_aggregator = msg_aggregator self.owned_eth_tokens = owned_eth_tokens self.accounts = blockchain_accounts # go through ETH accounts and make sure they are EIP55 encoded # TODO: really really bad thing here. Should not have to force mutate # a named tuple. Move this into the named tuple constructor self.accounts._replace( eth=[to_checksum_address(x) for x in self.accounts.eth]) # Per account balances self.balances: Balances = defaultdict(dict) # Per asset total balances self.totals: Totals = defaultdict(dict) # -- Cache related variables self.lock = Semaphore() self.results_cache: Dict[str, ResultCache] = {} self.cache_ttl_secs = CACHE_RESPONSE_FOR_SECS
def test_stakers_and_workers_relationships(testerchain, agency, test_registry): staking_agent = ContractAgency.get_agent(StakingEscrowAgent, registry=test_registry) staker_account, worker_account, *other = testerchain.unassigned_accounts # The staker hasn't bond a worker yet assert NULL_ADDRESS == staking_agent.get_worker_from_staker( staker_address=staker_account) tpower = TransactingPower(account=staker_account, signer=Web3Signer(testerchain.client)) _txhash = staking_agent.bond_worker(transacting_power=tpower, worker_address=worker_account) # We can check the staker-worker relation from both sides assert worker_account == staking_agent.get_worker_from_staker( staker_address=staker_account) assert staker_account == staking_agent.get_staker_from_worker( worker_address=worker_account) # No staker-worker relationship random_address = to_checksum_address(os.urandom(20)) assert NULL_ADDRESS == staking_agent.get_worker_from_staker( staker_address=random_address) assert NULL_ADDRESS == staking_agent.get_staker_from_worker( worker_address=random_address)
def _get_vaults_of_address( self, user_address: ChecksumEthAddress, proxy_address: ChecksumEthAddress, ) -> List[MakerDAOVault]: """Gets the vaults of a single address May raise: - RemoteError if etherscan is used and there is a problem with reaching it or with the returned result. - BlockchainQueryError if an ethereum node is used and the contract call queries fail for some reason """ result = MAKERDAO_GET_CDPS.call( ethereum=self.ethereum, method_name='getCdpsAsc', arguments=[MAKERDAO_CDP_MANAGER.address, proxy_address], ) vaults = [] for idx, identifier in enumerate(result[0]): urn = to_checksum_address(result[1][idx]) vault = self._query_vault_data( identifier=identifier, owner=user_address, urn=urn, ilk=result[2][idx], ) if vault: vaults.append(vault) self.vault_mappings[user_address].append(vault) return vaults
def remove_blockchain_account( self, blockchain: SupportedBlockchain, account: BlockchainAddress, ) -> None: if blockchain == SupportedBlockchain.ETHEREUM: account = to_checksum_address(account) self.db.remove_blockchain_account(blockchain, account)
def withdraw(self, blknum, txindex, oindex, tx, proof, sigs): utxo_pos = encode_utxo_id(blknum, txindex, oindex) encoded_transaction = rlp.encode(tx, UnsignedTransaction) print("encoded {}".format(encoded_transaction)) owner = tx.newowner1 if oindex == 0 else tx.newowner2 owner_addr = address.to_checksum_address('0x' + owner.hex()) bond = 1234567890 self.root_chain.startExit(utxo_pos, encoded_transaction, proof, sigs, transact={'from': owner_addr, 'value': bond})
def remove_blockchain_account( self, blockchain: typing.NonEthTokenBlockchainAsset, account: typing.BlockchainAddress, ) -> None: if blockchain == S_ETH: account = to_checksum_address(account) self.db.remove_blockchain_account(blockchain, account)
def test_keystore_sign_transaction(good_signer, mock_account): transaction_dict = assoc(TRANSACTION_DICT, 'from', value=mock_account.address) signed_transaction = good_signer.sign_transaction(transaction_dict=transaction_dict) assert isinstance(signed_transaction, HexBytes) # assert valid transaction transaction = Transaction.from_bytes(signed_transaction) assert to_checksum_address(transaction.to) == transaction_dict['to']
def signup(username, password) -> Tuple[Agency, Signer_Impl]: try: signer = create_account(username, password) agency = Agency(username = username, password = password) contract_addr = deploy_contract("Agency", signer = signer) agency.contract_addr = contract_addr agency.account_addr = str(signer.keypair.address) agency.account_pub = str(signer.keypair.public_key) agency.account_priv = str(signer.keypair.private_key) privkey, pubkey = gen_rsakey() agency.envelope_pub = pubkey agency.envelope_priv = privkey managementAddr = db.session.query(Contracts).filter(Contracts.name == "Management").first().addr EngineerListAddr = db.session.query(Contracts).filter(Contracts.name == "EngineerList").first().addr creditAddr = db.session.query(Contracts).filter(Contracts.name == "Credit").first().addr call_contract(contract_addr, "Agency", "setEngListAddr", args = [to_checksum_address(EngineerListAddr)], signer = signer) call_contract(contract_addr, "Agency", "setCreditAddr", args = [to_checksum_address(creditAddr)], signer = signer) agency.engineer_list_addr = EngineerListAddr # call_contract2(managementAddr, "Management", "addAgency", # args = [ # username, # to_checksum_address(agency.account_addr), # to_checksum_address(agency.contract_addr), # agency.envelope_pub, "" ], signer = signer) call_contract(managementAddr, "Management", "addAgency", args = [ username, to_checksum_address(agency.account_addr), to_checksum_address(agency.contract_addr), agency.envelope_pub, ""], signer = signer) db.session.add(agency) db.session.commit() except Exception: traceback.print_exc() db.session.rollback() return None, None return agency, signer
def verify_eip_191(address: str, message: bytes, signature: bytes) -> bool: """ EIP-191 Compatible signature verification for usage with w3.eth.sign. """ recovered_address = recover_address_eip_191(message=message, signature=signature) signature_is_valid = recovered_address == to_checksum_address(address) return signature_is_valid
def withdraw(self, blknum, txindex, oindex, tx, proof, sigs): utxo_pos = blknum * 1000000000 + txindex * 10000 + oindex * 1 encoded_transaction = rlp.encode(tx, UnsignedTransaction) _from = '' if oindex == 0: _from = address.to_checksum_address('0x' + tx.newowner1.hex()) else: _from = address.to_checksum_address('0x' + tx.newowner2.hex()) self.root_chain.startExit(utxo_pos, encoded_transaction, proof, sigs, transact={ 'from': _from, 'gas': 40000000 })
def hex_or_bytes_to_address(value: Union[bytes, str]) -> ChecksumEthAddress: """Turns a 32bit bytes/HexBytes or a hexstring into an address May raise: - ConversionError if it can't convert a value to an int or if an unexpected type is given. """ hexstr = hex_or_bytes_to_str(value) return ChecksumEthAddress(to_checksum_address('0x' + hexstr[26:]))
def recover_address_eip_191(message: bytes, signature: bytes) -> str: """ Recover checksum address from EIP-191 signature """ signable_message = encode_defunct(primitive=message) recovery = Account.recover_message(signable_message=signable_message, signature=signature) recovered_address = to_checksum_address(recovery) return recovered_address
def agency_evaluation(): username = session.get("username", "") password = session.get("password", "") agency, signer = login(username, password) if agency is None: return redirect("/agency") if request.method == "GET": return render_template("agency2-3.html", is_login = True, agency = agency, username = username) eva_addr = request.form.get("eva-addr") eva_accept = request.form.get("eva-accept") # eva_deny = request.form.get("eva-deny") result = True if eva_accept is not None else False eng_list = request.form.get("eng-list", "") eng_list = [e for e in eng_list.split()] if eva_addr is None: return render_template("agency2-3.html", is_login = True, agency = agency, username = username, fail_msg = "缺少审查合约地址") try: if result: call_contract(agency.contract_addr, "Agency", "confirm", args = [to_checksum_address(eva_addr), eng_list], signer = signer) else: res = call_contract(agency.contract_addr, "Agency", "deny", args = [to_checksum_address(eva_addr), eng_list], signer = signer) arbitrate_addr = res[0] if "0x000000000000000" in arbitrate_addr: raise Exception(msg = "Error arbitrate contract address") app.logger.info(f"{arbitrate_addr}") arbitrate = Arbitrate(addr = arbitrate_addr) db.session.add(arbitrate) db.session.commit() # call_contract(agency.contract_addr, "Agency", "addBusiness", [[], f"审查:审查合约地址{eva_addr}"], signer = signer) except Exception: traceback.print_exc() return render_template("agency2-3.html", is_login = True, agency = agency, username = username, fail_msg = "调用合约失败") if result: return render_template("agency2-3.html", is_login = True, agency = agency, username = username, succ_msg = "审查通过") return render_template("agency2-3.html", is_login = True, agency = agency, username = username, succ_msg = "审查拒绝")
def enterprise_evaluation(): username = session.get("username", "") password = session.get("password", "") enterprise, signer = login(username, password) if enterprise is None: return redirect("/enterprise") evaluation_addr = enterprise.evaluation_addr _, al, _, _ = count_numbers() if al < 3: return render_template("enterprise2.html", is_login=True, fail_msg="缺少足够的安评机构参与(至少3家安评机构)", enterprise=enterprise, username=username) if evaluation_addr is None: return render_template("enterprise2.html", is_login=True, fail_msg="缺少审查合约地址", enterprise=enterprise, username=username) try: managementAddr = db.session.query(Contracts).filter( Contracts.name == "Management").first().addr call_contract(evaluation_addr, "ReportEvaluation", "getAgencyList", args=[to_checksum_address(managementAddr)]) res = call_contract(evaluation_addr, "ReportEvaluation", "startEvaluation", signer=signer) ea_addr_list: List[str] = list(res[0]) except Exception: traceback.print_exc() return render_template("enterprise2.html", is_login=True, fail_msg="合约调用失败", enterprise=enterprise, username=username) result = [] for addr in ea_addr_list: ag = Agency.query.filter(Agency.contract_addr == addr).first() if ag is not None: result.append( (ag.username, addr, str(ag.envelope_pub, encoding="utf-8"))) # audit = random.choice(list(AuditList.values())) # result.append((audit.username, "")) return render_template("evaluation2.html", evaluation_addr=evaluation_addr, result=result)
def withdraw(self, blknum, txindex, oindex, tx, proof, sigs): utxo_pos = encode_utxo_id(blknum, txindex, oindex) encoded_transaction = rlp.encode(tx, UnsignedTransaction) owner = tx.newowner1 if oindex == 0 else tx.newowner2 owner_addr = address.to_checksum_address('0x' + owner.hex()) self.root_chain.startExit(utxo_pos, encoded_transaction, proof, sigs, transact={'from': owner_addr})
def get_multieth_balance( self, accounts: List[ChecksumEthAddress], ) -> Dict[ChecksumEthAddress, FVal]: """Returns a dict with keys being accounts and balances in ETH""" balances = {} if not self.connected: if len(accounts) > 20: new_accounts = [ accounts[x:x + 2] for x in range(0, len(accounts), 2) ] else: new_accounts = [accounts] for account_slice in new_accounts: log.debug( 'Querying etherscan for multiple accounts balance', sensitive_log=True, eth_accounts=account_slice, ) eth_resp = request_get_dict( 'https://api.etherscan.io/api?module=account&action=balancemulti&address=%s' % ','.join(account_slice), ) if eth_resp['status'] != 1: raise ValueError( 'Failed to query etherscan for accounts balance') eth_accounts = eth_resp['result'] for account_entry in eth_accounts: amount = FVal(account_entry['balance']) # Etherscan does not return accounts checksummed so make sure they # are converted properly here checksum_account = to_checksum_address( account_entry['account']) balances[checksum_account] = from_wei(amount) log.debug( 'Etherscan account balance result', sensitive_log=True, eth_address=account_entry['account'], wei_amount=amount, ) else: for account in accounts: amount = FVal(self.web3.eth.getBalance(account)) # pylint: disable=no-member log.debug( 'Ethereum node balance result', sensitive_log=True, eth_address=account, wei_amount=amount, ) balances[account] = from_wei(amount) return balances
def _checksum_eth_accounts_v1_to_v2(db: 'DBHandler') -> None: """Make sure all eth accounts are checksummed when saved in the DB""" cursor = db.conn.cursor() query = cursor.execute('SELECT account FROM blockchain_accounts where blockchain=?;', ('ETH',)) accounts = [x[0] for x in query] cursor.execute( 'DELETE FROM blockchain_accounts WHERE blockchain=?;', ('ETH',), ) db.conn.commit() tuples = [('ETH', to_checksum_address(account)) for account in accounts] cursor.executemany('INSERT INTO blockchain_accounts(blockchain, account) VALUES(?, ?)', tuples) db.conn.commit()