Repository: vyperlang/vyper

Issue:
Custom constants of lists
### Version Information

* vyper Version: 0.1.0 beta 7

### What's your issue about?
I'm not sure whether this is designed or a bug but Vyper doesn't support custom constants of lists.
It'd be better to support it if there is no concern?

```
# Invalid value for constant type, expected bytes[8] got bytes[8] instead
BYTE_LIST: constant(bytes[8]) = 'abcdefgh'

# 'ListType' object has no attribute 'is_literal'
BYTE32_LIST: constant(bytes32[2]) = [0x0000000000000000000000000000000000000000000000000000000000000000,
                                    0x0000000000000000000000000000000000000000000000000000000000000000]

# 'ListType' object has no attribute 'is_literal'
ZERO_LIST: constant(int128[8]) = [0, 0, 0, 0, 0, 0, 0, 0]

# 'ListType' object has no attribute 'is_literal'
ZERO_LIST: constant(uint256[8]) = [convert(0, uint256), convert(0, uint256), convert(0, uint256), convert(0, uint256), convert(0, uint256), convert(0, uint256), convert(0, uint256), convert(0, uint256)]
```

#### Cute Animal Picture

![image](https://user-images.githubusercontent.com/22876645/51522259-484fc780-1e6c-11e9-8f3d-46eb025a3aaf.png)



Discussion:
Hmmm I don't think we ever considered lists to be constants, not that could not be - just that it never was considered.
So now it begs the question - should we or not ?
Looks like the use case here is for an "empty list" or a list full of empty entries. @nrryuya are you looking for a way to assert that a list has not been set yet?
Well it's not the only use case, I can easily imagine something like a making sure you have set of values like:
```python
VALID_STATES:  constant(int128) = [1, 33, 44, 55 .. ]
```
Or another form of storing owners?
```python
OWNERS: constant(address[3]) = [....]
```
Just thinking out loud - on what it could be used for.
Case 1 would actually be better served by enums (which we don't have... yet). Basically something like:
```python
enum(int128) State:
    A = 1
    B = 33
    C = 44
    D = 55
```

Case 2 is typically done dynamically through a constructor. Probably not the best idea to hardcode a collection of addresses, since they might change on every deployment and you would have to update the code, but I can see a _limited_ rationale of how that could be useful for something like templated programs (but basically, just use constructor args)
>Looks like the use case here is for an "empty list" or a list full of empty entries. @nrryuya are you looking for a way to assert that a list has not been set yet?

Yep. I found this issue when I wanted to return a list full of `0` in my [BigInt.vy](https://github.com/LayerXcom/verified-vyper-contracts/pull/79) which represents a zero in a big number.

I'm also not confident about the use case of this feature...
As an example, we can use constants of a list of primes in programs like RSA Accumulator.
```
PRIMES: constant(int128[100]) = [2, 3, 5, ...]
```
List of primes might be a good one!

Resolving patch:
diff --git a/vyper/types/types.py b/vyper/types/types.py
--- a/vyper/types/types.py
+++ b/vyper/types/types.py
@@ -162,9 +162,10 @@ def __repr__(self):
 
 # Data structure for a list with some fixed length
 class ListType(NodeType):
-    def __init__(self, subtype, count):
+    def __init__(self, subtype, count, is_literal=False):
         self.subtype = subtype
         self.count = count
+        self.is_literal = is_literal
 
     def eq(self, other):
         return other.subtype == self.subtype and other.count == self.count


Test patch:
diff --git a/tests/parser/syntax/test_constants.py b/tests/parser/syntax/test_constants.py
--- a/tests/parser/syntax/test_constants.py
+++ b/tests/parser/syntax/test_constants.py
@@ -129,6 +129,15 @@ def test():
 def deposit(deposit_input: bytes[2048]):
     assert msg.value >= as_wei_value(MIN_DEPOSIT, "ether")
     assert msg.value <= as_wei_value(MAX_DEPOSIT, "ether")
+    """,
+    """
+BYTE32_LIST: constant(bytes32[2]) = [
+    0x0000000000000000000000000000000000000000000000000000000000000321,
+    0x0000000000000000000000000000000000000000000000000000000000000123
+]
+    """,
+    """
+ZERO_LIST: constant(int128[8]) = [0, 0, 0, 0, 0, 0, 0, 0]
     """
 ]
 
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
@@ -211,3 +211,33 @@ def test(some_dynamic_var: uint256) -> uint256:
 
     lll = compile_code(code, ['ir'])['ir']
     assert search_for_sublist(lll, ['add', ['mload', [320]], [4096]])
+
+
+def test_constant_lists(get_contract):
+    code = """
+BYTE32_LIST: constant(bytes32[2]) = [
+    0x0000000000000000000000000000000000000000000000000000000000001321,
+    0x0000000000000000000000000000000000000000000000000000000000001123
+]
+
+SPECIAL: constant(int128[3]) = [33, 44, 55]
+
+@public
+def test() -> bytes32:
+    a: bytes32[2] = BYTE32_LIST
+    return a[1]
+
+@constant
+@public
+def contains(a: int128) -> bool:
+    return a in SPECIAL
+    """
+
+    c = get_contract(code)
+
+    assert c.test()[-2:] == b'\x11\x23'
+
+    assert c.contains(55) is True
+    assert c.contains(44) is True
+    assert c.contains(33) is True
+    assert c.contains(3) is False