Repository: vyperlang/vyper

Issue:
`ZERO_WEI` constant can be defined with no effect
`ZERO_WEI` is a built-in constant, so it shouldn't be allowed as a user-defined constant:

```python
ZERO_WEI: constant(uint256(wei)) = 3
ONE_WEI: constant(uint256(wei)) = 5

@public
@constant
def zero() -> uint256(wei):
    return ZERO_WEI # returns 0, not 3

@public
@constant
def one() -> uint256(wei):
    return ONE_WEI # returns 5, as expected
```


Discussion:
Easy fix: disallow built-in constants from userland

Eventually consider namespacing? (Via #1347)

Resolving patch:
diff --git a/vyper/utils.py b/vyper/utils.py
--- a/vyper/utils.py
+++ b/vyper/utils.py
@@ -170,11 +170,12 @@ def in_bounds(cls, type_str, value):
     # control flow
     'if', 'for', 'while', 'until', 'pass',
     'def',
-    # EVM operations and transaction properties
+    # EVM operations
     'push', 'dup', 'swap', 'send', 'call',
     'selfdestruct', 'assert', 'stop', 'throw',
     'raise', 'init', '_init_', '___init___', '____init____',
-    'msg',
+    # environment variables
+    'block', 'msg', 'tx',
     # boolean literals
     'true', 'false',
     # more control flow and special operations
@@ -191,8 +192,8 @@ def in_bounds(cls, type_str, value):
     # units
     'units',
     # sentinal constant values
-    'zero_address', 'empty_bytes32' 'max_int128', 'min_int128', 'max_decimal',
-    'min_decimal', 'max_uint256',
+    'zero_address', 'empty_bytes32', 'max_int128', 'min_int128', 'max_decimal',
+    'min_decimal', 'max_uint256', 'zero_wei',
 }
 
 # Otherwise reserved words that are whitelisted for function declarations


Test patch:
diff --git a/tests/parser/types/numbers/test_constants.py b/tests/parser/types/numbers/test_constants.py
--- a/tests/parser/types/numbers/test_constants.py
+++ b/tests/parser/types/numbers/test_constants.py
@@ -113,15 +113,6 @@ def zoo() -> uint256:
     assert c.zoo() == 2**256 - 1
 
 
-def test_reserved_keyword(get_contract, assert_compile_failed):
-    code = """
-@public
-def test():
-    ZERO_ADDRESS: address
-    """
-    assert_compile_failed(lambda: get_contract(code))
-
-
 def test_custom_constants(get_contract):
     code = """
 X_VALUE: constant(uint256) = 33
diff --git a/tests/parser/types/test_variable_naming.py b/tests/parser/types/test_variable_naming.py
--- a/tests/parser/types/test_variable_naming.py
+++ b/tests/parser/types/test_variable_naming.py
@@ -8,6 +8,11 @@
 )
 from vyper.exceptions import (
     FunctionDeclarationException,
+    VariableDeclarationException,
+)
+from vyper.parser.expr import (
+    BUILTIN_CONSTANTS,
+    ENVIRONMENT_VARIABLES,
 )
 
 fail_list = [
@@ -34,3 +39,29 @@ def test_variable_naming_fail(bad_code):
 
     with raises(FunctionDeclarationException):
         compiler.compile_code(bad_code)
+
+
+@pytest.mark.parametrize('constant', list(BUILTIN_CONSTANTS)+list(ENVIRONMENT_VARIABLES))
+def test_reserved_keywords_memory(constant, get_contract, assert_compile_failed):
+    code = f"""
+@public
+def test():
+    {constant}: int128 = 31337
+    """
+    assert_compile_failed(lambda: get_contract(code), VariableDeclarationException)
+
+
+@pytest.mark.parametrize('constant', list(BUILTIN_CONSTANTS)+list(ENVIRONMENT_VARIABLES))
+def test_reserved_keywords_storage(constant, get_contract, assert_compile_failed):
+    code = f"{constant}: int128"
+    assert_compile_failed(lambda: get_contract(code), VariableDeclarationException)
+
+
+@pytest.mark.parametrize('constant', list(BUILTIN_CONSTANTS)+list(ENVIRONMENT_VARIABLES))
+def test_reserved_keywords_fn_args(constant, get_contract, assert_compile_failed):
+    code = f"""
+@public
+def test({constant}: int128):
+    pass
+    """
+    assert_compile_failed(lambda: get_contract(code), FunctionDeclarationException)