Repository: vyperlang/vyper

Issue:
VIP: Restrict usage of `msg` fields in public functions
## Simple Summary
Disallow using the `msg` context in public functions which are called internally.

## Abstract
This is kind of a follow-up to the discussion in https://github.com/ethereum/vyper/issues/901. The currently implemented behavior is to disallow `msg.sender` in private functions, forcing the caller to pass it as an explicit function argument. The behavior proposed here is to extend this restriction to public functions which are called internally, and also to extend it to the entire `msg` context. If a user really wants to call an internal `@public` function which accesses the `msg` context, they are forced to refactor the function to pass `msg.sender` explicitly (and optionally change it to `@private`).

## Motivation
`msg.sender` can have different values depending on if the function call is generated from an external caller or an internal caller. For instance,
```python
@public
def call1() -> address:
  return msg.sender
@private
def call2(addr: address) -> address:
  return addr  # Can't access `msg.sender` here, must pass as arg
@public
def call3() -> address:
  return call1()
@public
def call4() -> address:
  return call2(msg.sender)
```
In this example, `call1` and `call4` return the address of the caller, but `call3` returns the address of this contract. This goes against Vyper's principle of auditability since extra context needs to be reasoned about when reading code. This proposal would force the above implementation of `call1` to be changed to pass `msg.sender` as an argument, mimicking `call2`.

Additionally, the current behavior is an extra point of confusion for users coming from Solidity because Vyper's `@public` is more analogous to Solidity's `external` keyword than Solidity's `public` keyword (Solidity has a fine-grained distinction between `public` and `external` - `public` uses a jump which does not change the `msg` context, while `external` uses a message call).

## Specification
In addition to disallowing `msg.sender` in private functions, additionally disallow any `msg` values (off the top of my head: `msg.sender`, `msg.value`, proposed `msg.data`) in internal calls to public functions by raising an exception.

## Backwards Compatibility
`msg.sender` and friends are no longer allowed in public functions which are called internally.

## Copyright
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/)



Discussion:
An alternative to this proposal would be to only allow access to these variables in `@external` (similar to Solidity) as that context is meant to exclude access to other contract functions.
Tentative conclusion from gitter the other day was to disallow self calls to public functions entirely 
Calls to self if functions are public, will be prohibited. 

Resolving patch:
diff --git a/vyper/parser/external_call.py b/vyper/parser/external_call.py
--- a/vyper/parser/external_call.py
+++ b/vyper/parser/external_call.py
@@ -47,6 +47,10 @@ def external_contract_call(node,
             f'Contract "{contract_name}" not declared yet',
             node
         )
+    if contract_address.value == "address":
+        raise StructureException(
+            f"External calls to self are not permitted.", node
+        )
     method_name = node.func.attr
     if method_name not in context.sigs[contract_name]:
         raise FunctionDeclarationException(
diff --git a/vyper/parser/self_call.py b/vyper/parser/self_call.py
--- a/vyper/parser/self_call.py
+++ b/vyper/parser/self_call.py
@@ -64,10 +64,10 @@ def make_call(stmt_expr, context):
             getpos(stmt_expr)
         )
 
-    if sig.private:
-        return call_self_private(stmt_expr, context, sig)
-    else:
-        return call_self_public(stmt_expr, context, sig)
+    if not sig.private:
+        raise StructureException("Cannot call public functions via 'self'", stmt_expr)
+
+    return call_self_private(stmt_expr, context, sig)
 
 
 def call_make_placeholder(stmt_expr, context, sig):
@@ -299,29 +299,3 @@ def call_self_private(stmt_expr, context, sig):
     )
     o.gas += sig.gas
     return o
-
-
-def call_self_public(stmt_expr, context, sig):
-    # self.* style call to a public function.
-    method_name, expr_args, sig = call_lookup_specs(stmt_expr, context)
-    add_gas = sig.gas  # gas of call
-    inargs, inargsize, _ = pack_arguments(sig, expr_args, context, stmt_expr)
-    output_placeholder, returner, output_size = call_make_placeholder(stmt_expr, context, sig)
-    # don't have to use static call, trust self-call since constancy analysis
-    # already propagates.
-    assert_call = [
-        'assert',
-        ['call', ['gas'], ['address'], 0, inargs, inargsize, output_placeholder, output_size],
-    ]
-    if output_size > 0:
-        assert_call = ['seq', assert_call, returner]
-    o = LLLnode.from_list(
-        assert_call,
-        typ=sig.output_type,
-        location='memory',
-        pos=getpos(stmt_expr),
-        add_gas_estimate=add_gas,
-        annotation='Internal Call: %s' % method_name,
-    )
-    o.gas += sig.gas
-    return o


Test patch:
diff --git a/tests/parser/features/decorators/test_private.py b/tests/parser/features/decorators/test_private.py
--- a/tests/parser/features/decorators/test_private.py
+++ b/tests/parser/features/decorators/test_private.py
@@ -153,7 +153,7 @@ def set_greeting(_greeting: bytes[20]):
     if a + b + c + d + 3 == 1337:
         self.greeting = _greeting
 
-@public
+@private
 @constant
 def construct(greet: bytes[20]) -> bytes[40]:
     return concat(self.greeting, greet)
diff --git a/tests/parser/features/external_contracts/test_self_call_struct.py b/tests/parser/features/external_contracts/test_self_call_struct.py
--- a/tests/parser/features/external_contracts/test_self_call_struct.py
+++ b/tests/parser/features/external_contracts/test_self_call_struct.py
@@ -9,7 +9,7 @@ def test_call_to_self_struct(w3, get_contract):
     e1: decimal
     e2: timestamp
 
-@public
+@private
 @constant
 def get_my_struct(_e1: decimal, _e2: timestamp) -> MyStruct:
     return MyStruct({e1: _e1, e2: _e2})
diff --git a/tests/parser/features/test_internal_call.py b/tests/parser/features/test_internal_call.py
--- a/tests/parser/features/test_internal_call.py
+++ b/tests/parser/features/test_internal_call.py
@@ -15,13 +15,13 @@
 
 def test_selfcall_code(get_contract_with_gas_estimation):
     selfcall_code = """
-@public
-def foo() -> int128:
+@private
+def _foo() -> int128:
     return 3
 
 @public
 def bar() -> int128:
-    return self.foo()
+    return self._foo()
     """
 
     c = get_contract_with_gas_estimation(selfcall_code)
@@ -32,15 +32,15 @@ def bar() -> int128:
 
 def test_selfcall_code_2(get_contract_with_gas_estimation, keccak):
     selfcall_code_2 = """
-@public
-def double(x: int128) -> int128:
+@private
+def _double(x: int128) -> int128:
     return x * 2
 
 @public
 def returnten() -> int128:
-    return self.double(5)
+    return self._double(5)
 
-@public
+@private
 def _hashy(x: bytes32) -> bytes32:
     return keccak256(x)
 
@@ -58,7 +58,7 @@ def return_hash_of_rzpadded_cow() -> bytes32:
 
 def test_selfcall_code_3(get_contract_with_gas_estimation, keccak):
     selfcall_code_3 = """
-@public
+@private
 def _hashy2(x: bytes[100]) -> bytes32:
     return keccak256(x)
 
@@ -66,7 +66,7 @@ def _hashy2(x: bytes[100]) -> bytes32:
 def return_hash_of_cow_x_30() -> bytes32:
     return self._hashy2(b"cowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcow")  # noqa: E501
 
-@public
+@private
 def _len(x: bytes[100]) -> int128:
     return len(x)
 
@@ -84,37 +84,37 @@ def returnten() -> int128:
 
 def test_selfcall_code_4(get_contract_with_gas_estimation):
     selfcall_code_4 = """
-@public
-def summy(x: int128, y: int128) -> int128:
+@private
+def _summy(x: int128, y: int128) -> int128:
     return x + y
 
-@public
-def catty(x: bytes[5], y: bytes[5]) -> bytes[10]:
+@private
+def _catty(x: bytes[5], y: bytes[5]) -> bytes[10]:
     return concat(x, y)
 
-@public
-def slicey1(x: bytes[10], y: int128) -> bytes[10]:
+@private
+def _slicey1(x: bytes[10], y: int128) -> bytes[10]:
     return slice(x, start=0, len=y)
 
-@public
-def slicey2(y: int128, x: bytes[10]) -> bytes[10]:
+@private
+def _slicey2(y: int128, x: bytes[10]) -> bytes[10]:
     return slice(x, start=0, len=y)
 
 @public
 def returnten() -> int128:
-    return self.summy(3, 7)
+    return self._summy(3, 7)
 
 @public
 def return_mongoose() -> bytes[10]:
-    return self.catty(b"mon", b"goose")
+    return self._catty(b"mon", b"goose")
 
 @public
 def return_goose() -> bytes[10]:
-    return self.slicey1(b"goosedog", 5)
+    return self._slicey1(b"goosedog", 5)
 
 @public
 def return_goose2() -> bytes[10]:
-    return self.slicey2(5, b"goosedog")
+    return self._slicey2(5, b"goosedog")
     """
 
     c = get_contract_with_gas_estimation(selfcall_code_4)
@@ -130,14 +130,14 @@ def test_selfcall_code_5(get_contract_with_gas_estimation):
     selfcall_code_5 = """
 counter: int128
 
-@public
-def increment():
+@private
+def _increment():
     self.counter += 1
 
 @public
 def returnten() -> int128:
     for i in range(10):
-        self.increment()
+        self._increment()
     return self.counter
     """
     c = get_contract_with_gas_estimation(selfcall_code_5)
@@ -150,22 +150,22 @@ def test_selfcall_code_6(get_contract_with_gas_estimation):
     selfcall_code_6 = """
 excls: bytes[32]
 
-@public
-def set_excls(arg: bytes[32]):
+@private
+def _set_excls(arg: bytes[32]):
     self.excls = arg
 
-@public
-def underscore() -> bytes[1]:
+@private
+def _underscore() -> bytes[1]:
     return b"_"
 
-@public
-def hardtest(x: bytes[100], y: int128, z: int128, a: bytes[100], b: int128, c: int128) -> bytes[201]:  # noqa: E501
-    return concat(slice(x, start=y, len=z), self.underscore(), slice(a, start=b, len=c))
+@private
+def _hardtest(x: bytes[100], y: int128, z: int128, a: bytes[100], b: int128, c: int128) -> bytes[201]:  # noqa: E501
+    return concat(slice(x, start=y, len=z), self._underscore(), slice(a, start=b, len=c))
 
 @public
 def return_mongoose_revolution_32_excls() -> bytes[201]:
-    self.set_excls(b"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
-    return self.hardtest("megamongoose123", 4, 8, concat(b"russian revolution", self.excls), 8, 42)
+    self._set_excls(b"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
+    return self._hardtest("megamongoose123", 4, 8, concat(b"russian revolution", self.excls), 8, 42)
     """
 
     c = get_contract_with_gas_estimation(selfcall_code_6)
@@ -176,29 +176,33 @@ def return_mongoose_revolution_32_excls() -> bytes[201]:
 
 def test_list_call(get_contract_with_gas_estimation):
     code = """
-@public
-def foo0(x: int128[2]) -> int128:
+@private
+def _foo0(x: int128[2]) -> int128:
     return x[0]
 
-@public
-def foo1(x: int128[2]) -> int128:
+@private
+def _foo1(x: int128[2]) -> int128:
     return x[1]
 
 
+@public
+def foo1(x: int128[2]) -> int128:
+    return self._foo1(x)
+
 @public
 def bar() -> int128:
     x: int128[2]
-    return self.foo0(x)
+    return self._foo0(x)
 
 @public
 def bar2() -> int128:
     x: int128[2] = [55, 66]
-    return self.foo0(x)
+    return self._foo0(x)
 
 @public
 def bar3() -> int128:
     x: int128[2] = [55, 66]
-    return self.foo1(x)
+    return self._foo1(x)
     """
 
     c = get_contract_with_gas_estimation(code)
@@ -212,12 +216,12 @@ def test_list_storage_call(get_contract_with_gas_estimation):
     code = """
 y: int128[2]
 
-@public
-def foo0(x: int128[2]) -> int128:
+@private
+def _foo0(x: int128[2]) -> int128:
     return x[0]
 
-@public
-def foo1(x: int128[2]) -> int128:
+@private
+def _foo1(x: int128[2]) -> int128:
     return x[1]
 
 @public
@@ -226,11 +230,11 @@ def set():
 
 @public
 def bar0() -> int128:
-    return self.foo0(self.y)
+    return self._foo0(self.y)
 
 @public
 def bar1() -> int128:
-    return self.foo1(self.y)
+    return self._foo1(self.y)
     """
 
     c = get_contract_with_gas_estimation(code)
@@ -241,60 +245,64 @@ def bar1() -> int128:
 
 def test_multi_arg_list_call(get_contract_with_gas_estimation):
     code = """
-@public
-def foo0(y: decimal, x: int128[2]) -> int128:
+@private
+def _foo0(y: decimal, x: int128[2]) -> int128:
     return x[0]
 
-@public
-def foo1(x: int128[2], y: decimal) -> int128:
+@private
+def _foo1(x: int128[2], y: decimal) -> int128:
     return x[1]
 
-@public
-def foo2(y: decimal, x: int128[2]) -> decimal:
+@private
+def _foo2(y: decimal, x: int128[2]) -> decimal:
     return y
 
-@public
-def foo3(x: int128[2], y: decimal) -> int128:
+@private
+def _foo3(x: int128[2], y: decimal) -> int128:
     return x[0]
 
-@public
-def foo4(x: int128[2], y: int128[2]) -> int128:
+@private
+def _foo4(x: int128[2], y: int128[2]) -> int128:
     return y[0]
 
 
+@public
+def foo1(x: int128[2], y: decimal) -> int128:
+    return self._foo1(x, y)
+
 @public
 def bar() -> int128:
     x: int128[2]
-    return self.foo0(0.3434, x)
+    return self._foo0(0.3434, x)
 
 # list as second parameter
 @public
 def bar2() -> int128:
     x: int128[2] = [55, 66]
-    return self.foo0(0.01, x)
+    return self._foo0(0.01, x)
 
 @public
 def bar3() -> decimal:
     x: int128[2] = [88, 77]
-    return self.foo2(1.33, x)
+    return self._foo2(1.33, x)
 
 # list as first parameter
 @public
 def bar4() -> int128:
     x: int128[2] = [88, 77]
-    return self.foo1(x, 1.33)
+    return self._foo1(x, 1.33)
 
 @public
 def bar5() -> int128:
     x: int128[2] = [88, 77]
-    return self.foo3(x, 1.33)
+    return self._foo3(x, 1.33)
 
 # two lists
 @public
 def bar6() -> int128:
     x: int128[2] = [88, 77]
     y: int128[2] = [99, 66]
-    return self.foo4(x, y)
+    return self._foo4(x, y)
 
     """
 
@@ -309,12 +317,12 @@ def bar6() -> int128:
 
 def test_multi_mixed_arg_list_call(get_contract_with_gas_estimation):
     code = """
-@public
-def fooz(x: int128[2], y: decimal, z: int128[2], a: decimal) -> int128:
+@private
+def _fooz(x: int128[2], y: decimal, z: int128[2], a: decimal) -> int128:
     return z[1]
 
-@public
-def fooa(x: int128[2], y: decimal, z: int128[2], a: decimal) -> decimal:
+@private
+def _fooa(x: int128[2], y: decimal, z: int128[2], a: decimal) -> decimal:
     return a
 
 @public
@@ -324,7 +332,7 @@ def bar() -> (int128, decimal):
     z: int128[2] = [55, 66]
     a: decimal = 66.77
 
-    return self.fooz(x, y, z, a), self.fooa(x, y, z, a)
+    return self._fooz(x, y, z, a), self._fooa(x, y, z, a)
     """
     c = get_contract_with_gas_estimation(code)
     assert c.bar() == [66, Decimal('66.77')]
@@ -356,18 +364,19 @@ def bar2() -> int128:
 
 def test_multi_mixed_arg_list_bytes_call(get_contract_with_gas_estimation):
     code = """
-@public
-def fooz(x: int128[2], y: decimal, z: bytes[11], a: decimal) -> bytes[11]:
+@private
+def _fooz(x: int128[2], y: decimal, z: bytes[11], a: decimal) -> bytes[11]:
     return z
 
-@public
-def fooa(x: int128[2], y: decimal, z: bytes[11], a: decimal) -> decimal:
+@private
+def _fooa(x: int128[2], y: decimal, z: bytes[11], a: decimal) -> decimal:
     return a
 
-@public
-def foox(x: int128[2], y: decimal, z: bytes[11], a: decimal) -> int128:
+@private
+def _foox(x: int128[2], y: decimal, z: bytes[11], a: decimal) -> int128:
     return x[1]
 
+
 @public
 def bar() -> (bytes[11], decimal, int128):
     x: int128[2] = [33, 44]
@@ -375,7 +384,7 @@ def bar() -> (bytes[11], decimal, int128):
     z: bytes[11] = b"hello world"
     a: decimal = 66.77
 
-    return self.fooz(x, y, z, a), self.fooa(x, y, z, a), self.foox(x, y, z, a)
+    return self._fooz(x, y, z, a), self._fooa(x, y, z, a), self._foox(x, y, z, a)
     """
     c = get_contract_with_gas_estimation(code)
     assert c.bar() == [b"hello world", Decimal('66.77'), 44]
@@ -411,6 +420,30 @@ def bar(a: int128) -> int128:
 @public
 def foo() -> int128:
     return self.bar(1, 2)
+    """,
+    """
+# should not compile - public to public
+@public
+def bar() -> int128:
+    return 1
+
+@public
+def foo() -> int128:
+    return self.bar()
+    """,
+    """
+# should not compile - private to public
+@public
+def bar() -> int128:
+    return 1
+
+@private
+def _baz() -> int128:
+    return self.bar()
+
+@public
+def foo() -> int128:
+    return self._baz()
     """
 ]
 
diff --git a/tests/parser/features/test_logging_from_call.py b/tests/parser/features/test_logging_from_call.py
--- a/tests/parser/features/test_logging_from_call.py
+++ b/tests/parser/features/test_logging_from_call.py
@@ -3,12 +3,12 @@ def test_log_dynamic_static_combo(get_logs, get_contract_with_gas_estimation, w3
     code = """
 TestLog: event({testData1: bytes32,testData2: bytes[60], testData3: bytes[8]})
 
-@public
+@private
 @constant
 def to_bytes(value: uint256) -> bytes[8]:
     return slice(concat(b"", convert(value, bytes32)), start=24, len=8)
 
-@public
+@private
 @constant
 def to_bytes32(value: uint256) -> bytes32:
     return convert(value, bytes32)
@@ -44,12 +44,12 @@ def test_log_dynamic_static_combo2(get_logs, get_contract, w3):
     code = """
 TestLog: event({testData1: bytes32,testData2: bytes[133], testData3: bytes[8] })
 
-@public
+@private
 @constant
 def to_bytes(value: uint256) -> bytes[8]:
     return slice(concat(b"", convert(value, bytes32)), start=24, len=8)
 
-@public
+@private
 @constant
 def to_bytes32(value: uint256) -> bytes32:
     return convert(value, bytes32)
@@ -82,7 +82,7 @@ def test_log_single_function_call(get_logs, get_contract, w3):
     code = """
 TestLog: event({testData1: bytes32, testData2: bytes[133]})
 
-@public
+@private
 @constant
 def to_bytes32(value: uint256) -> bytes32:
     return convert(value, bytes32)
@@ -112,7 +112,7 @@ def test_original_problem_function(get_logs, get_contract, w3):
     code = """
 TestLog: event({testData1: bytes32,testData2: bytes[2064], testData3: bytes[8] })
 
-@public
+@private
 @constant
 def to_bytes(value: uint256) -> bytes[8]:
     return slice(concat(b"", convert(value, bytes32)), start=24, len=8)
diff --git a/tests/parser/features/test_units.py b/tests/parser/features/test_units.py
--- a/tests/parser/features/test_units.py
+++ b/tests/parser/features/test_units.py
@@ -103,7 +103,7 @@ def foo(a: uint256, b: uint256, c: uint256) -> uint256:
 
 def test_function_call_explicit_unit_literal(get_contract, assert_compile_failed):
     code = """
-@public
+@private
 def unit_func(a: uint256(wei)) -> uint256(wei):
     return a + 1
 
diff --git a/tests/parser/functions/test_interfaces.py b/tests/parser/functions/test_interfaces.py
--- a/tests/parser/functions/test_interfaces.py
+++ b/tests/parser/functions/test_interfaces.py
@@ -409,3 +409,62 @@ def foo() -> uint256:
     global_compiled = compile_codes(codes, interface_codes=global_interface_codes)
     local_compiled = compile_codes(codes, interface_codes=local_interface_codes)
     assert global_compiled == local_compiled
+
+
+def test_self_interface_cannot_compile(assert_compile_failed):
+    code = """
+contract Bar:
+    def foo() -> uint256: constant
+
+@public
+def foo() -> uint256 :
+    return 42
+
+@public
+def bar() -> uint256:
+    return Bar(self).foo()
+"""
+    assert_compile_failed(
+        lambda: compile_code(code),
+        StructureException
+    )
+
+
+def test_self_interface_via_storage_raises(get_contract, assert_tx_failed):
+    code = """
+contract Bar:
+    def foo() -> uint256: constant
+
+bar_contract: Bar
+
+@public
+def __init__():
+    self.bar_contract = Bar(self)
+
+@public
+def foo() -> uint256 :
+    return 42
+
+@public
+def bar() -> uint256:
+    return self.bar_contract.foo()
+    """
+    c = get_contract(code)
+    assert_tx_failed(lambda: c.bar())
+
+
+def test_self_interface_via_calldata_raises(get_contract, assert_tx_failed):
+    code = """
+contract Bar:
+    def foo() -> uint256: constant
+
+@public
+def foo() -> uint256 :
+    return 42
+
+@public
+def bar(a: address) -> uint256:
+    return Bar(a).foo()
+    """
+    c = get_contract(code)
+    assert_tx_failed(lambda: c.bar(c.address))
diff --git a/tests/parser/functions/test_return_tuple.py b/tests/parser/functions/test_return_tuple.py
--- a/tests/parser/functions/test_return_tuple.py
+++ b/tests/parser/functions/test_return_tuple.py
@@ -83,19 +83,21 @@ def out_literals() -> (int128, address, bytes[6]):
 
 def test_return_tuple_assign(get_contract_with_gas_estimation):
     code = """
-@public
-def out_literals() -> (int128, address, bytes[10]):
+@private
+def _out_literals() -> (int128, address, bytes[10]):
     return 1, 0x0000000000000000000000000000000000000000, b"random"
 
+@public
+def out_literals() -> (int128, address, bytes[10]):
+    return self._out_literals()
 
 @public
 def test() -> (int128, address, bytes[10]):
     a: int128
     b: address
     c: bytes[10]
-    (a, b, c) = self.out_literals()
+    (a, b, c) = self._out_literals()
     return a, b, c
-
     """
 
     c = get_contract_with_gas_estimation(code)
@@ -110,26 +112,29 @@ def test_return_tuple_assign_storage(get_contract_with_gas_estimation):
 c: bytes[20]
 d: bytes[20]
 
-@public
-def out_literals() -> (int128, bytes[20], address, bytes[20]):
+@private
+def _out_literals() -> (int128, bytes[20], address, bytes[20]):
     return 1, b"testtesttest", 0x0000000000000000000000000000000000000023, b"random"
 
+@public
+def out_literals() -> (int128, bytes[20], address, bytes[20]):
+    return self._out_literals()
 
 @public
 def test1() -> (int128, bytes[20], address, bytes[20]):
-    self.a, self.c, self.b, self.d = self.out_literals()
+    self.a, self.c, self.b, self.d = self._out_literals()
     return self.a, self.c, self.b, self.d
 
 @public
 def test2() -> (int128, address):
     x: int128
-    x, self.c, self.b, self.d = self.out_literals()
+    x, self.c, self.b, self.d = self._out_literals()
     return x, self.b
 
 @public
 def test3() -> (address, int128):
     x: address
-    self.a, self.c, x, self.d = self.out_literals()
+    self.a, self.c, x, self.d = self._out_literals()
     return x, self.a
     """
 
diff --git a/tests/parser/integration/test_basics.py b/tests/parser/integration/test_basics.py
--- a/tests/parser/integration/test_basics.py
+++ b/tests/parser/integration/test_basics.py
@@ -23,7 +23,7 @@ def foo(x: int128) -> int128:
 
 def test_selfcall_code_3(get_contract_with_gas_estimation, keccak):
     selfcall_code_3 = """
-@public
+@private
 def _hashy2(x: bytes[100]) -> bytes32:
     return keccak256(x)
 
@@ -31,7 +31,7 @@ def _hashy2(x: bytes[100]) -> bytes32:
 def return_hash_of_cow_x_30() -> bytes32:
     return self._hashy2("cowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcow")  # noqa: E501
 
-@public
+@private
 def _len(x: bytes[100]) -> int128:
     return len(x)
 
diff --git a/tests/parser/syntax/test_invalids.py b/tests/parser/syntax/test_invalids.py
--- a/tests/parser/syntax/test_invalids.py
+++ b/tests/parser/syntax/test_invalids.py
@@ -213,7 +213,7 @@ def foo():
 """)
 
 must_succeed("""
-@public
+@private
 def foo():
     pass
 
diff --git a/tests/parser/syntax/test_send.py b/tests/parser/syntax/test_send.py
--- a/tests/parser/syntax/test_send.py
+++ b/tests/parser/syntax/test_send.py
@@ -90,7 +90,7 @@ def foo():
     """,
     """
 # Test custom send method
-@public
+@private
 def send(a: address, w: wei_value):
     send(0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe, 1)
 
diff --git a/tests/parser/syntax/test_tuple_assign.py b/tests/parser/syntax/test_tuple_assign.py
--- a/tests/parser/syntax/test_tuple_assign.py
+++ b/tests/parser/syntax/test_tuple_assign.py
@@ -22,7 +22,7 @@ def test():
     a, b, c = 1, 2, 3
     """, VariableDeclarationException),
     """
-@public
+@private
 def out_literals() -> (int128, int128, bytes[10]):
     return 1, 2, b"3333"
 
@@ -34,7 +34,7 @@ def test() -> (int128, address, bytes[10]):
     return a, b, c
     """,
     """
-@public
+@private
 def out_literals() -> (int128, int128, bytes[10]):
     return 1, 2, b"3333"
 
@@ -46,7 +46,7 @@ def test() -> (int128, address, bytes[10]):
     return
     """,
     """
-@public
+@private
 def out_literals() -> (int128, int128, int128):
     return 1, 2, 3
 
@@ -59,7 +59,7 @@ def test() -> (int128, int128, bytes[10]):
     return a, b, c
     """,
     """
-@public
+@private
 def out_literals() -> (int128, int128, bytes[100]):
     return 1, 2, b"test"