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 invalid address literal #3621

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,6 @@ def foo():
def foo():
log Foo("abcd")
""",
# Address literal must be checksummed
"""
a: constant(address) = 0x3cd751e6b0078be393132286c442345e5dc49699
""",
]


Expand Down
9 changes: 9 additions & 0 deletions tests/functional/syntax/test_ann_assign.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

from vyper import compiler
from vyper.exceptions import (
BadChecksumAddress,
InvalidAttribute,
TypeMismatch,
UndeclaredDefinition,
Expand Down Expand Up @@ -125,6 +126,14 @@ def foo() -> bool:
""",
TypeMismatch,
),
(
"""
@external
def foo():
x: address = 0x6b175474e89094c44da98b954eedeac495271d0F
""",
BadChecksumAddress,
),
]


Expand Down
8 changes: 8 additions & 0 deletions tests/functional/syntax/test_constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from vyper import compiler
from vyper.exceptions import (
ArgumentException,
BadChecksumAddress,
ImmutableViolation,
NamespaceCollision,
StateAccessViolation,
Expand Down Expand Up @@ -171,6 +172,13 @@ def hello() :
""",
ImmutableViolation,
),
# invalid checksum address
(
"""
a: constant(address) = 0x3cd751e6b0078be393132286c442345e5dc49699
""",
BadChecksumAddress,
),
]


Expand Down
22 changes: 18 additions & 4 deletions tests/unit/ast/nodes/test_hex.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from vyper import ast as vy_ast
from vyper import semantics
from vyper.exceptions import InvalidLiteral
from vyper.exceptions import BadChecksumAddress, InvalidLiteral

code_invalid_checksum = [
"""
Expand All @@ -27,6 +27,18 @@
for i: address in [0x6b175474e89094c44da98b954eedeac495271d0F]:
pass
""",
]


@pytest.mark.parametrize("code", code_invalid_checksum)
def test_bad_checksum_address(code, dummy_input_bundle):
vyper_module = vy_ast.parse_to_ast(code)

with pytest.raises(BadChecksumAddress):
semantics.validate_semantics(vyper_module, dummy_input_bundle)


code_invalid_literal = [
"""
foo: constant(bytes20) = 0x6b175474e89094c44da98b954eedeac495271d0F
""",
Expand All @@ -36,8 +48,10 @@
]


@pytest.mark.parametrize("code", code_invalid_checksum)
def test_invalid_checksum(code, dummy_input_bundle):
@pytest.mark.parametrize("code", code_invalid_literal)
def test_invalid_literal(code, dummy_input_bundle):
vyper_module = vy_ast.parse_to_ast(code)

with pytest.raises(InvalidLiteral):
vyper_module = vy_ast.parse_to_ast(code)
semantics.analyze_module(vyper_module, dummy_input_bundle)
semantics.validate_semantics(vyper_module, dummy_input_bundle)
4 changes: 4 additions & 0 deletions vyper/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,10 @@ class InvalidLiteral(VyperException):
"""Invalid literal value."""


class BadChecksumAddress(InvalidLiteral):
"""Invalid literal address value."""


class InvalidAttribute(VyperException):
"""Reference to an attribute that does not exist."""

Expand Down
19 changes: 16 additions & 3 deletions vyper/semantics/analysis/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

from vyper import ast as vy_ast
from vyper.exceptions import (
BadChecksumAddress,
CompilerPanic,
InvalidLiteral,
InvalidOperation,
Expand All @@ -24,7 +25,7 @@
from vyper.semantics.types.bytestrings import BytesT, StringT
from vyper.semantics.types.primitives import AddressT, BoolT, BytesM_T, IntegerT
from vyper.semantics.types.subscriptable import DArrayT, SArrayT, TupleT
from vyper.utils import checksum_encode, int_to_fourbytes
from vyper.utils import int_to_fourbytes


def _validate_op(node, types_list, validation_fn_name):
Expand Down Expand Up @@ -312,7 +313,17 @@ def types_from_Constant(self, node):
raise OverflowException(
"Numeric literal is outside of allowable range for number types", node
)
raise InvalidLiteral(f"Could not determine type for literal value '{node.value}'", node)

hint = ""
if isinstance(node, vy_ast.Hex) and len(node.value) == 42:
# call `validate_literal` for its side effect of throwing an exception for
# address checksum mismatch
try:
AddressT().validate_literal(node)
except BadChecksumAddress as e:
hint += e.message

raise InvalidLiteral(f"Could not determine type for literal value '{node.value}'", node, hint=hint)

def types_from_IfExp(self, node):
validate_expected_type(node.test, BoolT())
Expand Down Expand Up @@ -609,7 +620,9 @@ def validate_expected_type(node, expected_type):

suggestion_str = ""
if expected_type[0] == AddressT() and given_types[0] == BytesM_T(20):
suggestion_str = f" Did you mean {checksum_encode(node.value)}?"
# call `validate_literal` for its side effect of throwing an exception for
# address checksum mismatch
AddressT().validate_literal(node)

raise TypeMismatch(
f"Expected {expected_str} but literal can only be cast as {given_str}.{suggestion_str}",
Expand Down
3 changes: 2 additions & 1 deletion vyper/semantics/types/primitives.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from vyper import ast as vy_ast
from vyper.abi_types import ABI_Address, ABI_Bool, ABI_BytesM, ABI_FixedMxN, ABI_GIntM, ABIType
from vyper.exceptions import (
BadChecksumAddress,
CompilerPanic,
InvalidLiteral,
InvalidOperation,
Expand Down Expand Up @@ -384,7 +385,7 @@ def validate_literal(self, node: vy_ast.Constant) -> None:

addr = node.value
if not is_checksum_encoded(addr):
raise InvalidLiteral(
raise BadChecksumAddress(
"Address checksum mismatch. If you are sure this is the right "
f"address, the correct checksummed form is: {checksum_encode(addr)}",
node,
Expand Down
Loading