From 9d9b53327b103ca40a0a8da5a96094978d6715f2 Mon Sep 17 00:00:00 2001 From: Tim Date: Tue, 19 Mar 2024 12:11:18 -0400 Subject: [PATCH] token handling fix for bytes32 results --- src/dexorder/contract/__init__.py | 2 ++ src/dexorder/contract/abi.py | 2 +- src/dexorder/tokens.py | 33 ++++++++++++++++++++----------- 3 files changed, 24 insertions(+), 13 deletions(-) diff --git a/src/dexorder/contract/__init__.py b/src/dexorder/contract/__init__.py index 94f8b04..b2e7f42 100644 --- a/src/dexorder/contract/__init__.py +++ b/src/dexorder/contract/__init__.py @@ -8,6 +8,8 @@ from ..base.chain import current_chain def get_contract_data(name): + if name in abis: + return {'abi':abis[name]} if name == "Vault" and os.path.exists(f'../contract/out/I{name}.sol/I{name}.json') : # logging.debug("getting abi from IVault.json instead of Vault.json") name = "IVault" # Special case for proxy Vault diff --git a/src/dexorder/contract/abi.py b/src/dexorder/contract/abi.py index cdffb5e..68e0b0a 100644 --- a/src/dexorder/contract/abi.py +++ b/src/dexorder/contract/abi.py @@ -1,5 +1,5 @@ abis = { # ERC20 where symbol() returns a bytes32 instead of a string - 'ERC20.sb': '''[{"type":"function","name":"symbol","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"}]''' + 'ERC20.sb': '''[{"type":"function","name":"symbol","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"name","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"}]''' # 'WMATIC': '''[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"guy","type":"address"},{"name":"wad","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"src","type":"address"},{"name":"dst","type":"address"},{"name":"wad","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"wad","type":"uint256"}],"name":"withdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"dst","type":"address"},{"name":"wad","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"deposit","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":true,"name":"src","type":"address"},{"indexed":true,"name":"guy","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"src","type":"address"},{"indexed":true,"name":"dst","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"dst","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"src","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Withdrawal","type":"event"}]''', } diff --git a/src/dexorder/tokens.py b/src/dexorder/tokens.py index 8f93320..a9c81ca 100644 --- a/src/dexorder/tokens.py +++ b/src/dexorder/tokens.py @@ -27,26 +27,35 @@ async def get_token(address) -> Optional[TokenDict]: async def load_token(address: str) -> Optional[TokenDict]: contract = ERC20(address) - name_prom = contract.name() - dec_prom = contract.decimals() - try: - symbol = await contract.symbol() - except (InsufficientDataBytes, BadFunctionCallOutput): - # this happens when the token returns bytes32 instead of a string + + async def get_string_or_bytes32(func_name): try: - symbol = await ContractProxy(address, 'ERC20.sb').symbol() - log.info(f'got bytes32 symbol {symbol}') - except (InsufficientDataBytes, ContractLogicError, BadFunctionCallOutput): - log.warning(f'token {address} has broken symbol()') - return None + result = await getattr(contract, func_name)() + except (InsufficientDataBytes, BadFunctionCallOutput, OverflowError): + # this happens when the token returns bytes32 instead of a string + try: + rb: bytes = await ContractProxy(address, 'ERC20.sb').symbol() + end = rb.find(b'\x00') + if end == -1: + end = 32 + result = rb[:end].decode('utf8') + except (InsufficientDataBytes, ContractLogicError, BadFunctionCallOutput): + log.warning(f'token {address} has broken {func_name}()') + return None + return result + + dec_prom = contract.decimals() + symbol_prom = get_string_or_bytes32('symbol') + name_prom = get_string_or_bytes32('name') try: decimals = await dec_prom except (InsufficientDataBytes, ContractLogicError, BadFunctionCallOutput): log.warning(f'token {address} has no decimals()') decimals = 0 - name = await name_prom approved = config.metadata is None chain_id = current_chain.get().chain_id + symbol = await symbol_prom + name = await name_prom td = TokenDict(type='Token', chain=chain_id, address=address, name=name, symbol=symbol, decimals=decimals, approved=approved) md = get_metadata(address, chain_id=chain_id)