Repository: vyperlang/vyper

Issue:
Remove __init__ name from abi json.
### Version Information

### What's your issue about?
Remove non-standard 'name' attribute from the constructor function.
Remove non-standard 'name' attribute from the default function.

e.g.
`{"name": "__init__", "outputs": [], "inputs": [], "constant": false, "payable": false, "type": "constructor"}`

### How can it be fixed?

For `__default__`:

* Investigate ABIv2 expectations for the "fallback" function feature
* Remove field "name" from ABI output (in Vyper, as in Python, `__[underscored_names]__` should _never_ be used externally)
* Change the "type" field to "fallback"
* It appears that the fallback cannot have the fields "inputs" or "outputs" as it does not decode data explicitly (leaving it to internal use of #1181 to decode passed data)


Discussion:
Starting on this.

Resolving patch:
diff --git a/vyper/compiler.py b/vyper/compiler.py
--- a/vyper/compiler.py
+++ b/vyper/compiler.py
@@ -55,9 +55,9 @@ def mk_full_signature(code, *args, **kwargs):
     # Add gas estimates for each function to ABI
     gas_estimates = gas_estimate(code, *args, **kwargs)
     for idx, func in enumerate(abi):
-        func_name = func['name'].split('(')[0]
+        func_name = func.get('name', '').split('(')[0]
         # Skip __init__, has no estimate
-        if func_name in gas_estimates and func_name != '__init__':
+        if func_name in gas_estimates:
             abi[idx]['gas'] = gas_estimates[func_name]
     return abi
 
diff --git a/vyper/parser/parser.py b/vyper/parser/parser.py
--- a/vyper/parser/parser.py
+++ b/vyper/parser/parser.py
@@ -137,7 +137,7 @@ def generate_default_arg_sigs(code, contracts, global_ctx):
 def mk_full_signature(code, sig_formatter=None, interface_codes=None):
 
     if sig_formatter is None:
-        # Use default JSON style ouptu.
+        # Use default JSON style output.
         sig_formatter = lambda sig, custom_units_descriptions: sig.to_abi_dict(custom_units_descriptions)
 
     o = []
diff --git a/vyper/signatures/function_signature.py b/vyper/signatures/function_signature.py
--- a/vyper/signatures/function_signature.py
+++ b/vyper/signatures/function_signature.py
@@ -171,6 +171,12 @@ def _generate_output_abi(self, custom_units_descriptions=None):
         return abi_outputs
 
     def to_abi_dict(self, custom_units_descriptions=None):
+        func_type = "function"
+        if self.name == "__init__":
+            func_type = "constructor"
+        if self.name == "__default__":
+            func_type = "fallback"
+
         abi_dict = {
             "name": self.name,
             "outputs": self._generate_output_abi(custom_units_descriptions),
@@ -181,12 +187,18 @@ def to_abi_dict(self, custom_units_descriptions=None):
             } for arg in self.args],
             "constant": self.const,
             "payable": self.payable,
-            "type": "constructor" if self.name == "__init__" else "function"
+            "type": func_type
         }
 
         for abi_input in abi_dict['inputs']:
             delete_unit_if_empty(abi_input)
 
+        if self.name in ('__default__', '__init__'):
+            del abi_dict['name']
+        if self.name == '__default__':
+            del abi_dict['inputs']
+            del abi_dict['outputs']
+
         return abi_dict
 
     @classmethod


Test patch:
diff --git a/tests/conftest.py b/tests/conftest.py
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -41,7 +41,7 @@ def __call__(self, *args, **kwargs):
     def __prepared_function(self, *args, **kwargs):
         if not kwargs:
             modifier, modifier_dict = 'call', {}
-            fn_abi = [x for x in self._function.contract_abi if x['name'] == self._function.function_identifier].pop()
+            fn_abi = [x for x in self._function.contract_abi if x.get('name') == self._function.function_identifier].pop()
             modifier_dict.update({'gas': fn_abi.get('gas', 0) + 50000})  # To make tests faster just supply some high gas value.
         elif len(kwargs) == 1:
             modifier, modifier_dict = kwargs.popitem()
diff --git a/tests/parser/functions/test_only_init_abi.py b/tests/parser/functions/test_abi.py
similarity index 67%
rename from tests/parser/functions/test_only_init_abi.py
rename to tests/parser/functions/test_abi.py
--- a/tests/parser/functions/test_only_init_abi.py
+++ b/tests/parser/functions/test_abi.py
@@ -18,7 +18,6 @@ def __init__():
     """
 
     empty_sig = [{
-        'name': '__init__',
         'outputs': [],
         'inputs': [],
         'constant': False,
@@ -28,3 +27,18 @@ def __init__():
 
     assert mk_full_signature(code) == empty_sig
     assert mk_full_signature(code_init_empty) == empty_sig
+
+
+def test_default_abi():
+    default_code = """
+@payable
+@public
+def __default__():
+    pass
+    """
+
+    assert mk_full_signature(default_code) == [{
+        'constant': False,
+        'payable': True,
+        'type': 'fallback'
+    }]