Repository: vyperlang/vyper

Issue:
VIP: remove casting in signature
## Preamble

    VIP: 749
    Title: Remove casting in signature feature
    Author: Denis Bogdanas
    Type: Standard Track
    Status: Draft
    Created: 2018-04-03


## Simple Summary
Remove the ability to cast `uint256` to `int128` in function signature.

## Abstract
Casting in signature:
https://github.com/ethereum/vyper/blob/3eb961ecccb8ced76f19217843bb9ee88f6f8750/tests/parser/types/numbers/test_num256.py#L130

can be completely replaced with plain conversion to `int128`.

## Motivation
Looks like a language redundancy that can be removed. The only diff is that `convert()` also performs a clamp, and requires defining a new variable. None of these should be issues.

## Specification
Replace casting in signature with `convert(x, "int128")` inside function.

## Backwards Compatibility
Casting instances should be replaced.

## Copyright
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/)



Discussion:
I 100% agree. This is not a great feature for auditability and should be removed
:+1: since uint256 is way more compatible. I vote we remove it before alpha?
Agree. Just add it to the final countdown so we can track it.

<sub>Sent with <a href="http://githawk.com">GitHawk</a></sub>
New project "fix the beta" :smile: 
Oh yeah I see, awesome!

<sub>Sent with <a href="http://githawk.com">GitHawk</a></sub>

Resolving patch:
diff --git a/vyper/parser/parser_utils.py b/vyper/parser/parser_utils.py
--- a/vyper/parser/parser_utils.py
+++ b/vyper/parser/parser_utils.py
@@ -479,8 +479,6 @@ def base_type_conversion(orig, frm, to, pos):
         return LLLnode(orig.value, orig.args, typ=to, add_gas_estimate=orig.add_gas_estimate)
     elif is_base_type(frm, 'int128') and is_base_type(to, 'decimal') and are_units_compatible(frm, to):
         return LLLnode.from_list(['mul', orig, DECIMAL_DIVISOR], typ=BaseType('decimal', to.unit, to.positional))
-    elif is_base_type(frm, 'uint256') and is_base_type(to, 'int128') and are_units_compatible(frm, to):
-        return LLLnode.from_list(['uclample', orig, ['mload', MemoryPositions.MAXNUM]], typ=BaseType('int128'))
     elif isinstance(frm, NullType):
         if to.typ not in ('int128', 'bool', 'uint256', 'address', 'bytes32', 'decimal'):
             # This is only to future proof the use of  base_type_conversion.
diff --git a/vyper/types/types.py b/vyper/types/types.py
--- a/vyper/types/types.py
+++ b/vyper/types/types.py
@@ -165,13 +165,10 @@ def canonicalize_type(t, is_indexed=False):
         )
     if not isinstance(t, BaseType):
         raise Exception("Cannot canonicalize non-base type: %r" % t)
-    uint256_override = True if t.override_signature == 'uint256' else False
 
     t = t.typ
-    if t == 'int128' and not uint256_override:
+    if t == 'int128':
         return 'int128'
-    elif t == 'int128' and uint256_override:
-        return 'uint256'
     elif t == 'decimal':
         return 'fixed168x10'
     elif t == 'bool':
@@ -255,9 +252,6 @@ def parse_type(item, location, sigs=None, custom_units=None):
             argz = item.args
         if len(argz) != 1:
             raise InvalidTypeException("Malformed unit type", item)
-        # Check for uint256 to num casting
-        if item.func.id == 'int128' and getattr(item.args[0], 'id', '') == 'uint256':
-            return BaseType('int128', override_signature='uint256')
         unit = parse_unit(argz[0], custom_units=custom_units)
         return BaseType(base_type, unit, positional)
     # Subscripts


Test patch:
diff --git a/tests/parser/types/numbers/test_uint256.py b/tests/parser/types/numbers/test_uint256.py
--- a/tests/parser/types/numbers/test_uint256.py
+++ b/tests/parser/types/numbers/test_uint256.py
@@ -121,40 +121,6 @@ def _uint256_exp(x: uint256, y: uint256) -> uint256:
     assert c._uint256_exp(7**23, 3) == 7**69
 
 
-def test_uint256_to_num_casting(assert_tx_failed, get_contract_with_gas_estimation):
-    code = """
-@public
-def _uint256_to_num(x: int128(uint256)) -> int128:
-    return x
-
-@public
-def _uint256_to_num_call(x: uint256) -> int128:
-    return self._uint256_to_num(x)
-
-@public
-def built_in_conversion(x: uint256) -> int128:
-    return convert(x, 'int128')
-    """
-
-    c = get_contract_with_gas_estimation(code)
-
-    # Ensure uint256 function signature.
-    assert c._classic_contract.functions.abi[0]['inputs'][0]['type'] == 'uint256'
-
-    assert c._uint256_to_num(1) == 1
-    assert c._uint256_to_num((2**127) - 1) == 2**127 - 1
-    assert_tx_failed(lambda: c._uint256_to_num((2**128)) == 0)
-    assert c._uint256_to_num_call(1) == 1
-
-    # Check that casting matches manual conversion
-    assert c._uint256_to_num_call(2**127 - 1) == c.built_in_conversion(2**127 - 1)
-
-    # Pass in negative int.
-    # assert_tx_failed(lambda: c._uint256_to_num(-1) != -1, ValueOutOfBounds)
-    # Make sure it can't be coherced into a negative number.
-    assert_tx_failed(lambda: c._uint256_to_num_call(2**127))
-
-
 def test_modmul(get_contract_with_gas_estimation):
     modexper = """
 @public