Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

raise_contract_logic_error_on_revert fails with UnicodeDecodeError #2969

Closed
sanekto opened this issue May 29, 2023 · 1 comment · Fixed by #2989
Closed

raise_contract_logic_error_on_revert fails with UnicodeDecodeError #2969

sanekto opened this issue May 29, 2023 · 1 comment · Fixed by #2989

Comments

@sanekto
Copy link
Contributor

sanekto commented May 29, 2023

  • Version: 6.4.0
  • Python: 3.10
  • OS: linux
  • pip freeze output
aiohttp==3.8.4
aiosignal==1.3.1
async-timeout==4.0.2
attrs==23.1.0
bitarray==2.7.3
cached-property==1.5.2
certifi==2023.5.7
charset-normalizer==3.1.0
coverage==7.2.6
cytoolz==0.12.1
eth-abi==4.0.0
eth-account==0.8.0
eth-bloom==2.0.0
eth-hash==0.5.1
eth-keyfile==0.6.1
eth-keys==0.4.0
eth-rlp==0.3.0
eth-typing==3.3.0
eth-utils==2.1.0
frozenlist==1.3.3
hexbytes==0.3.0
idna==3.4
iniconfig==2.0.0
jsonschema==4.17.3
lru-dict==1.2.0
multidict==6.0.4
mypy-extensions==0.4.4
packaging==23.1
parsimonious==0.9.0
pluggy==1.0.0
protobuf==4.23.2
py-ecc==6.0.0
py-evm==0.7.0a2
pycryptodome==3.18.0
pyethash==0.1.27
pyrsistent==0.19.3
pytest==7.3.1
pytest-cov==4.1.0
regex==2023.5.5
requests==2.31.0
rlp==3.0.0
safe-eth-py==5.4.3
safe-pysha3==1.0.4
sortedcontainers==2.4.0
toolz==0.12.0
trie==2.1.0
urllib3==2.0.2
web3==6.4.0
websockets==11.0.3
yarl==1.9.2

What was wrong?

Function raise_contract_logic_error_on_revert raises UnicodeDecodeError when parsing receipt for the following response
response = {'error': {'code': -32015, 'data': 'Reverted 0xd27b44a9', 'message': 'VM execution error.'}, 'id': 3, 'jsonrpc': '2.0'}

/opt/hostedtoolcache/Python/3.10.11/x64/lib/python3.10/site-packages/web3/contract/contract.py:461: in call
    return call_contract_function(
/opt/hostedtoolcache/Python/3.10.11/x64/lib/python3.10/site-packages/web3/contract/utils.py:96: in call_contract_function
    return_data = w3.eth.call(
/opt/hostedtoolcache/Python/3.10.11/x64/lib/python3.10/site-packages/web3/eth/eth.py:255: in call
    return self._durin_call(transaction, block_identifier, state_override)
/opt/hostedtoolcache/Python/3.10.11/x64/lib/python3.10/site-packages/web3/eth/eth.py:274: in _durin_call
    return self._call(transaction, block_identifier, state_override)
/opt/hostedtoolcache/Python/3.10.11/x64/lib/python3.10/site-packages/web3/module.py:68: in caller
    result = w3.manager.request_blocking(
/opt/hostedtoolcache/Python/3.10.11/x64/lib/python3.10/site-packages/web3/manager.py:232: in request_blocking
    return self.formatted_response(
/opt/hostedtoolcache/Python/3.10.11/x64/lib/python3.10/site-packages/web3/manager.py:197: in formatted_response
    apply_error_formatters(error_formatters, response)
/opt/hostedtoolcache/Python/3.10.11/x64/lib/python3.10/site-packages/web3/manager.py:73: in apply_error_formatters
    formatted_resp = pipe(response, error_formatters)
cytoolz/functoolz.pyx:666: in cytoolz.functoolz.pipe
    ???
cytoolz/functoolz.pyx:641: in cytoolz.functoolz.c_pipe
    ???
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

response = {'error': {'code': -32015, 'data': 'Reverted 0xd27b44a9', 'message': 'VM execution error.'}, 'id': 3, 'jsonrpc': '2.0'}

    def raise_contract_logic_error_on_revert(response: RPCResponse) -> RPCResponse:
        """
        Reverts contain a `data` attribute with the following layout:
            "Reverted "
            Function selector for Error(string): 08c379a (4 bytes)
            Data offset: 32 (32 bytes)
            String length (32 bytes)
            Reason string (padded, use string length from above to get meaningful part)
    
        See also https://solidity.readthedocs.io/en/v0.6.3/control-structures.html#revert
        """
        if not isinstance(response["error"], dict):
            raise ValueError("Error expected to be a dict")
    
        data = response["error"].get("data", "")
    
        # Ganache case:
        if isinstance(data, dict) and response["error"].get("message"):
            raise ContractLogicError(
                f'execution reverted: {response["error"]["message"]}', data=data
            )
    
        # Parity/OpenEthereum case:
        if data.startswith("Reverted "):
            # "Reverted", function selector and offset are always the same for revert errors
            prefix = "Reverted 0x08c379a00000000000000000000000000000000000000000000000000000000000000020"  # noqa: 501
            if not data.startswith(prefix):
                if data.startswith("Reverted 0x"):
                    # Special case for this form: 'Reverted 0x...'
                    receipt = data.split(" ")[1][2:]
>                   revert_reason = bytes.fromhex(receipt).decode("utf-8")
E                   UnicodeDecodeError: 'utf-8' codec can't decode byte 0xd2 in position 0: invalid continuation byte

/opt/hostedtoolcache/Python/3.10.11/x64/lib/python3.10/site-packages/web3/_utils/method_formatters.py:743: UnicodeDecodeError
@fselmo
Copy link
Collaborator

fselmo commented Jun 5, 2023

It seems like the message is not able to be decoded. I don't particularly like the current flow of assuming that it can be decoded. Perhaps we can catch the UnicodeDecodeError and raise ContractLogicError with just the raw data. That might be the most constructive way to handle it.

fselmo added a commit to fselmo/web3.py that referenced this issue Jun 8, 2023
- If we can't decode the revert reason string, simply raise the ``ContractLogicError`` with the raw data and issue a warning that there was an issue decoding a reason string.
@fselmo fselmo mentioned this issue Jun 8, 2023
1 task
fselmo added a commit that referenced this issue Jun 8, 2023
- If we can't decode the revert reason string, simply raise the ``ContractLogicError`` with the raw data and issue a warning that there was an issue decoding a reason string.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants