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

chore: improve error message for non-checksummed address literal #3065

Merged
merged 8 commits into from
Aug 13, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions tests/parser/exceptions/test_invalid_type_exception.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import pytest
from pytest import raises

from vyper import compiler
from vyper.exceptions import InvalidType, UnknownType

fail_list = [
Expand All @@ -25,9 +23,8 @@


@pytest.mark.parametrize("bad_code", fail_list)
def test_unknown_type_exception(bad_code):
with raises(UnknownType):
compiler.compile_code(bad_code)
def test_unknown_type_exception(bad_code, get_contract, assert_compile_failed):
assert_compile_failed(lambda: get_contract(bad_code), UnknownType)


invalid_list = [
Expand Down Expand Up @@ -68,10 +65,13 @@ def mint(_to: address, _value: uint256):
"""
b: HashMap[(int128, decimal), int128]
""",
# Address literal must be checksummed
"""
a: constant(address) = 0x3cd751e6b0078be393132286c442345e5dc49699
""",
]


@pytest.mark.parametrize("bad_code", invalid_list)
def test_invalid_type_exception(bad_code):
with raises(InvalidType):
compiler.compile_code(bad_code)
def test_invalid_type_exception(bad_code, get_contract, assert_compile_failed):
assert_compile_failed(lambda: get_contract(bad_code), InvalidType)
12 changes: 11 additions & 1 deletion vyper/semantics/validation/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,11 @@
DynamicArrayDefinition,
TupleDefinition,
)
from vyper.semantics.types.value.address import AddressDefinition
from vyper.semantics.types.value.boolean import BoolDefinition
from vyper.semantics.types.value.bytes_fixed import Bytes20Definition # type: ignore
from vyper.semantics.validation.levenshtein_utils import get_levenshtein_error_suggestions
from vyper.utils import checksum_encode


def _validate_op(node, types_list, validation_fn_name):
Expand Down Expand Up @@ -456,9 +459,16 @@ def validate_expected_type(node, expected_type):
types_str = sorted(str(i) for i in given_types)
given_str = f"{', '.join(types_str[:1])} or {types_str[-1]}"

suggestion_str = ""
if isinstance(expected_type[0], AddressDefinition) and isinstance(
given_types[0], Bytes20Definition
):
suggestion_str = f" Did you mean {checksum_encode(node.value)}?"

# CMC 2022-02-14 maybe TypeMismatch would make more sense here
raise InvalidType(
f"Expected {expected_str} but literal can only be cast as {given_str}", node
f"Expected {expected_str} but literal can only be cast as {given_str}.{suggestion_str}",
node,
)


Expand Down