diff --git a/newsfragments/1794.bugfix.rst b/newsfragments/1794.bugfix.rst new file mode 100644 index 0000000000..f289ce8fed --- /dev/null +++ b/newsfragments/1794.bugfix.rst @@ -0,0 +1 @@ +Handle revert reason parsing for Ganache diff --git a/tests/core/utilities/test_method_formatters.py b/tests/core/utilities/test_method_formatters.py index 1dd367f165..ae75f09ae7 100644 --- a/tests/core/utilities/test_method_formatters.py +++ b/tests/core/utilities/test_method_formatters.py @@ -14,6 +14,7 @@ RPCResponse, ) +# OpenEthereum/default case: REVERT_WITH_MSG = RPCResponse({ 'jsonrpc': '2.0', 'error': { @@ -49,16 +50,48 @@ "id": 1, }) +GETH_RESPONSE = RPCResponse({ + 'jsonrpc': '2.0', + 'id': 2, + 'error': { + 'code': 3, + 'message': 'execution reverted: Function has been reverted.', + 'data': ( + '0x08c379a0000000000000000000000000000000000000000000000' + '0000000000000000020000000000000000000000000000000000000' + '000000000000000000000000001b46756e6374696f6e20686173206' + '265656e2072657665727465642e0000000000' + ), + }, +}) + +GANACHE_RESPONSE = RPCResponse({ + 'id': 24, + 'jsonrpc': '2.0', + 'error': { + 'message': 'VM Exception while processing transaction: revert Custom revert message', + 'code': -32000, + 'data': { + 'stack': 'o: VM Exception while processing transaction: revert Custom revert message\n', + 'name': 'o' + } + } +}) + @pytest.mark.parametrize( "response,expected", ( (REVERT_WITH_MSG, 'execution reverted: not allowed to monitor'), (REVERT_WITHOUT_MSG, 'execution reverted'), + (GETH_RESPONSE, 'execution reverted: Function has been reverted.'), + (GANACHE_RESPONSE, 'execution reverted: VM Exception while processing transaction: revert Custom revert message'), # noqa: 501 ), ids=[ 'test-get-revert-reason-with-msg', 'test-get-revert-reason-without-msg', + 'test-get-geth-revert-reason', + 'test_get-ganache-revert-reason', ]) def test_get_revert_reason(response, expected) -> None: with pytest.raises(SolidityError, match=expected): diff --git a/web3/_utils/method_formatters.py b/web3/_utils/method_formatters.py index 6c83d6b110..6c45a7f206 100644 --- a/web3/_utils/method_formatters.py +++ b/web3/_utils/method_formatters.py @@ -485,8 +485,13 @@ def raise_solidity_error_on_revert(response: RPCResponse) -> RPCResponse: if not isinstance(response['error'], dict): raise ValueError('Error expected to be a dict') - # Parity/OpenEthereum case: data = response['error'].get('data', '') + + # Ganache case: + if isinstance(data, dict) and response['error'].get('message'): + raise SolidityError(f'execution reverted: {response["error"]["message"]}') + + # Parity/OpenEthereum case: if data.startswith('Reverted '): # "Reverted", function selector and offset are always the same for revert errors prefix = 'Reverted 0x08c379a00000000000000000000000000000000000000000000000000000000000000020' # noqa: 501