Repository: vyperlang/vyper

Issue:
Event logging doesn't handle the situation when the type of a variable ListType.
### What's your issue about?
Two programs:
```
Bar: __log__({_value: num[2]})

@public
def foo():
    log.Bar([1, 2])
```
```
Bar: __log__({_value: num[2]})

@public
def foo():
    a = [1, 2]
    log.Bar(a)
```
The first program compiles but the second program throws python exception "AttributeError: 'Name' object has no attribute 'elts'" because `pack_args_by_32` only handles list literals.

### How can it be fixed?

In `pack_args_by_32`, add logic to handle variable of ListType.

#### Cute Animal Picture

![image](https://user-images.githubusercontent.com/5641590/33298951-e299f978-d3ae-11e7-84ce-d7e5ffc59312.png)




Discussion:
On it. :+1: thanks @yzhang90 :)

Resolving patch:
diff --git a/viper/parser/parser.py b/viper/parser/parser.py
--- a/viper/parser/parser.py
+++ b/viper/parser/parser.py
@@ -697,9 +697,19 @@ def pack_args_by_32(holder, maxlen, arg, typ, context, placeholder):
     elif isinstance(typ, ListType):
             maxlen += (typ.count - 1) * 32
             typ = typ.subtype
-            holder, maxlen = pack_args_by_32(holder, maxlen, arg.elts[0], typ, context, placeholder)
-            for j, arg2 in enumerate(arg.elts[1:]):
-                holder, maxlen = pack_args_by_32(holder, maxlen, arg2, typ, context, context.new_placeholder(BaseType(32)))
+
+            if isinstance(arg, ast.Name):
+                size = context.vars[arg.id].size
+                pos = context.vars[arg.id].pos
+                for i in range(0, size):
+                    offset = 32 * i
+                    arg2 = LLLnode.from_list(pos + offset, typ=typ, location='memory')
+                    holder, maxlen = pack_args_by_32(holder, maxlen, arg2, typ, context, context.new_placeholder(BaseType(32)))
+            else:  # is list literal.
+                holder, maxlen = pack_args_by_32(holder, maxlen, arg.elts[0], typ, context, placeholder)
+                for j, arg2 in enumerate(arg.elts[1:]):
+                    holder, maxlen = pack_args_by_32(holder, maxlen, arg2, typ, context, context.new_placeholder(BaseType(32)))
+
     return holder, maxlen
 
 


Test patch:
diff --git a/tests/parser/features/test_logging.py b/tests/parser/features/test_logging.py
--- a/tests/parser/features/test_logging.py
+++ b/tests/parser/features/test_logging.py
@@ -1,6 +1,6 @@
 import pytest
 from tests.setup_transaction_tests import chain as s, tester as t, ethereum_utils as u, check_gas, \
-    get_contract_with_gas_estimation, get_contract
+    get_contract_with_gas_estimation, get_contract, assert_tx_failed, get_last_log
 from viper.exceptions import VariableDeclarationException, TypeMismatchException, StructureException
 
 
@@ -511,3 +511,60 @@ def ioo(inp: bytes <= 100):
     c.ioo(b"moo4")
     assert s.head_state.receipts[-1].logs[0].data == b'moo4'
     print("Passed raw log tests")
+
+
+def test_variable_list_packing(get_last_log):
+    code = """
+Bar: __log__({_value: num[4]})
+
+@public
+def foo():
+    a = [1, 2, 3, 4]
+    log.Bar(a)
+    """
+    c = get_contract_with_gas_estimation(code)
+
+    c.foo()
+    assert get_last_log(t, c)["_value"] == [1, 2, 3, 4]
+
+
+def test_literal_list_packing(get_last_log):
+    code = """
+Bar: __log__({_value: num[4]})
+
+@public
+def foo():
+    log.Bar([1, 2, 3, 4])
+    """
+    c = get_contract_with_gas_estimation(code)
+
+    c.foo()
+    assert get_last_log(t, c)["_value"] == [1, 2, 3, 4]
+
+
+def test_passed_list_packing(get_last_log):
+    code = """
+Bar: __log__({_value: num[4]})
+
+@public
+def foo(barbaric: num[4]):
+    log.Bar(barbaric)
+    """
+    c = get_contract_with_gas_estimation(code)
+
+    c.foo([4, 5, 6, 7])
+    assert get_last_log(t, c)["_value"] == [4, 5, 6, 7]
+
+
+def test_variable_decimal_list_packing(get_last_log):
+    code = """
+Bar: __log__({_value: decimal[4]})
+
+@public
+def foo():
+    log.Bar([1.11, 2.22, 3.33, 4.44])
+    """
+    c = get_contract_with_gas_estimation(code)
+
+    c.foo()
+    assert get_last_log(t, c)["_value"] == [1.11, 2.22, 3.33, 4.44]