Repository: vyperlang/vyper

Issue:
ABI "gas" bound doesn't generate with Immutable variables
### Version Information

* vyper Version (output of `vyper --version`): 0.3.1
* OS: osx
* Python Version (output of `python --version`):  3.8.6

### What's your issue about?

Learning how immutable variable works

testing this contract:

```
TOKEN_A: immutable(address)

@external
def __init__(a: address):
    TOKEN_A = a


@external
def tokenss() -> address:
    return TOKEN_A
```

Generated abi was without gas:

`[{"stateMutability": "nonpayable", "type": "constructor", "inputs": [{"name": "a", "type": "address"}], "outputs": []}, {"stateMutability": "nonpayable", "type": "function", "name": "tokenss", "inputs": [], "outputs": [{"name": "", "type": "address"}]}]
`

**without:**
```
token: public(address)

@external
def __init__(a: address):
    self.token = a


@external
def tokenss() -> address:
    return self.token
```

`[{"stateMutability": "nonpayable", "type": "constructor", "inputs": [{"name": "a", "type": "address"}], "outputs": []}, {"stateMutability": "nonpayable", "type": "function", "name": "tokenss", "inputs": [], "outputs": [{"name": "", "type": "address"}], "gas": 2460}, {"stateMutability": "view", "type": "function", "name": "token", "inputs": [], "outputs": [{"name": "", "type": "address"}], "gas": 2490}]
`



Please include information like:

* full output of the error you received
* what command you ran
* the code that caused the failure (see [this link](https://help.github.com/articles/basic-writing-and-formatting-syntax/) for help with formatting code)
* please try running your example with the --debug flag turned on


### How can it be fixed?

Fill this in if you know how to fix it.



Discussion:

Resolving patch:
diff --git a/vyper/compiler/output.py b/vyper/compiler/output.py
--- a/vyper/compiler/output.py
+++ b/vyper/compiler/output.py
@@ -99,7 +99,7 @@ def build_method_identifiers_output(compiler_data: CompilerData) -> dict:
 def build_abi_output(compiler_data: CompilerData) -> list:
     abi = compiler_data.vyper_module_folded._metadata["type"].to_abi_dict()
     # Add gas estimates for each function to ABI
-    gas_estimates = build_gas_estimates(compiler_data.lll_nodes)
+    gas_estimates = build_gas_estimates(compiler_data.lll_runtime)
     for func in abi:
         try:
             func_signature = func["name"]
diff --git a/vyper/compiler/utils.py b/vyper/compiler/utils.py
--- a/vyper/compiler/utils.py
+++ b/vyper/compiler/utils.py
@@ -1,18 +1,10 @@
 from vyper.old_codegen.lll_node import LLLnode
 
 
-def build_gas_estimates(lll_nodes: LLLnode) -> dict:
+def build_gas_estimates(lll_runtime: LLLnode) -> dict:
     gas_estimates: dict = {}
 
-    # Extract the stuff inside the LLL bracket
-    if (
-        lll_nodes.value == "seq"
-        and len(lll_nodes.args) > 0
-        and lll_nodes.args[-1].value == "return"
-    ):
-        lll_nodes = lll_nodes.args[-1].args[1].args[1]
-
-    external_sub = next((i for i in lll_nodes.args if i.value == "with"), None)
+    external_sub = next((i for i in lll_runtime.args if i.value == "with"), None)
     if external_sub:
         for func_lll in external_sub.args[-1].args:
             if func_lll.func_name is not None:
diff --git a/vyper/evm/opcodes.py b/vyper/evm/opcodes.py
--- a/vyper/evm/opcodes.py
+++ b/vyper/evm/opcodes.py
@@ -187,6 +187,7 @@
     "UCLAMPLT": (None, 2, 1, 25),
     "UCLAMPLE": (None, 2, 1, 30),
     "CLAMP_NONZERO": (None, 1, 1, 19),
+    "CODELOAD": (None, 1, 1, 9),
     "ASSERT": (None, 1, 0, 85),
     "ASSERT_UNREACHABLE": (None, 1, 0, 17),
     "PASS": (None, 0, 0, 0),


Test patch:
diff --git a/tests/conftest.py b/tests/conftest.py
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -111,11 +111,11 @@ def get_contract_module(source_code, *args, **kwargs):
 
 
 def get_compiler_gas_estimate(code, func):
-    lll_nodes = compiler.phases.CompilerData(code).lll_nodes
+    lll_runtime = compiler.phases.CompilerData(code).lll_runtime
     if func:
-        return compiler.utils.build_gas_estimates(lll_nodes)[func] + 22000
+        return compiler.utils.build_gas_estimates(lll_runtime)[func] + 22000
     else:
-        return sum(compiler.utils.build_gas_estimates(lll_nodes).values()) + 22000
+        return sum(compiler.utils.build_gas_estimates(lll_runtime).values()) + 22000
 
 
 def check_gas_on_chain(w3, tester, code, func=None, res=None):