Repository: vyperlang/vyper

Issue:
Overflow checking for multiplication
### What's your issue about?
`NOT` in EVM is bitwise NOT, not logical `NOT`. So the overflow checking for multiplication (`['assert', ['or', ['eq', ['sdiv', 'ans', 'l'], 'r'], ['not', 'l']]]` ) is wrong. Consider the following the test cases:
```
def test_mul_overflow(t, assert_tx_failed, get_contract_with_gas_estimation, chain):
    mul_code = """

@public
def _num_mul(x: decimal, y: int128) -> decimal:
    return x * y

    """

    c = get_contract_with_gas_estimation(mul_code)

    t.s = chain
    NUM_1 = 85070591730234615865843651857942052864.0
    NUM_2 = 136112946768375385385349842973

    assert_tx_failed(lambda: c._num_mul(NUM_1, NUM_2))
```
 NUM_1 * NUM_2 > 2**127, but no exception is thrown. 


### How can it be fixed?

Use `ISZERO` to test whether `l` is zero.

#### Cute Animal Picture

![image](https://user-images.githubusercontent.com/5641590/38502679-a4b213b8-3bd5-11e8-97dc-f350ff731465.png)



Discussion:

Resolving patch:
diff --git a/vyper/parser/expr.py b/vyper/parser/expr.py
--- a/vyper/parser/expr.py
+++ b/vyper/parser/expr.py
@@ -242,13 +242,13 @@ def arithmetic(self):
                 o = LLLnode.from_list(['with', 'r', right, ['with', 'l', left,
                                         ['with', 'ans', ['mul', 'l', 'r'],
                                             ['seq',
-                                                ['assert', ['or', ['eq', ['sdiv', 'ans', 'l'], 'r'], ['not', 'l']]],
+                                                ['assert', ['or', ['eq', ['sdiv', 'ans', 'l'], 'r'], ['iszero', 'l']]],
                                                 ['sdiv', 'ans', DECIMAL_DIVISOR]]]]], typ=BaseType('decimal', new_unit), pos=getpos(self.expr))
             elif (ltyp == 'int128' and rtyp == 'decimal') or (ltyp == 'decimal' and rtyp == 'int128'):
                 o = LLLnode.from_list(['with', 'r', right, ['with', 'l', left,
                                         ['with', 'ans', ['mul', 'l', 'r'],
                                             ['seq',
-                                                ['assert', ['or', ['eq', ['sdiv', 'ans', 'l'], 'r'], ['not', 'l']]],
+                                                ['assert', ['or', ['eq', ['sdiv', 'ans', 'l'], 'r'], ['iszero', 'l']]],
                                                 'ans']]]], typ=BaseType('decimal', new_unit), pos=getpos(self.expr))
             else:
                 raise Exception("Unsupported Operation 'mul(%r, %r)'" % (ltyp, rtyp))


Test patch:
diff --git a/tests/parser/types/numbers/test_decimals.py b/tests/parser/types/numbers/test_decimals.py
--- a/tests/parser/types/numbers/test_decimals.py
+++ b/tests/parser/types/numbers/test_decimals.py
@@ -121,3 +121,21 @@ def iarg() -> wei_value:
     assert c.iarg() == 14
 
     print('Passed fractional multiplication test')
+
+
+def test_mul_overflow(t, assert_tx_failed, get_contract_with_gas_estimation, chain):
+    mul_code = """
+
+@public
+def _num_mul(x: decimal, y: int128) -> decimal:
+    return x * y
+
+    """
+
+    c = get_contract_with_gas_estimation(mul_code)
+
+    t.s = chain
+    NUM_1 = 85070591730234615865843651857942052864.0
+    NUM_2 = 136112946768375385385349842973
+
+    assert_tx_failed(lambda: c._num_mul(NUM_1, NUM_2))