From b932371e4c4b57237a4c40c0d255f5b9e8dfb170 Mon Sep 17 00:00:00 2001
From: webthethird <ratzbodell@gmail.com>
Date: Wed, 24 May 2023 12:55:10 -0500
Subject: [PATCH 1/2] Avoid IndexError in `is_function_modified`

---
 slither/utils/upgradeability.py | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/slither/utils/upgradeability.py b/slither/utils/upgradeability.py
index 7b4e8493a7..9fb55ce81a 100644
--- a/slither/utils/upgradeability.py
+++ b/slither/utils/upgradeability.py
@@ -220,6 +220,8 @@ def is_function_modified(f1: Function, f2: Function) -> bool:
         visited.extend([node_f1, node_f2])
         queue_f1.extend(son for son in node_f1.sons if son not in visited)
         queue_f2.extend(son for son in node_f2.sons if son not in visited)
+        if len(node_f1.irs) != len(node_f2.irs):
+            return True
         for i, ir in enumerate(node_f1.irs):
             if encode_ir_for_compare(ir) != encode_ir_for_compare(node_f2.irs[i]):
                 return True

From 58391ae487406a1ed1870028a5e50d0bf80af3b1 Mon Sep 17 00:00:00 2001
From: webthethird <ratzbodell@gmail.com>
Date: Wed, 24 May 2023 12:57:12 -0500
Subject: [PATCH 2/2] Improve encoding for comparison

---
 slither/utils/upgradeability.py | 17 ++++++++++++-----
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/slither/utils/upgradeability.py b/slither/utils/upgradeability.py
index 9fb55ce81a..8d18dd67c0 100644
--- a/slither/utils/upgradeability.py
+++ b/slither/utils/upgradeability.py
@@ -275,13 +275,13 @@ def encode_ir_for_compare(ir: Operation) -> str:
     if isinstance(ir, Assignment):
         return f"({encode_var_for_compare(ir.lvalue)}):=({encode_var_for_compare(ir.rvalue)})"
     if isinstance(ir, Index):
-        return f"index({ntype(ir.index_type)})"
+        return f"index({ntype(ir.variable_right.type)})"
     if isinstance(ir, Member):
         return "member"  # .format(ntype(ir._type))
     if isinstance(ir, Length):
         return "length"
     if isinstance(ir, Binary):
-        return f"binary({str(ir.variable_left)}{str(ir.type)}{str(ir.variable_right)})"
+        return f"binary({encode_var_for_compare(ir.variable_left)}{ir.type}{encode_var_for_compare(ir.variable_right)})"
     if isinstance(ir, Unary):
         return f"unary({str(ir.type)})"
     if isinstance(ir, Condition):
@@ -332,7 +332,7 @@ def encode_var_for_compare(var: Variable) -> str:
 
     # variables
     if isinstance(var, Constant):
-        return f"constant({ntype(var.type)})"
+        return f"constant({ntype(var.type)},{var.value})"
     if isinstance(var, SolidityVariableComposed):
         return f"solidity_variable_composed({var.name})"
     if isinstance(var, SolidityVariable):
@@ -342,9 +342,16 @@ def encode_var_for_compare(var: Variable) -> str:
     if isinstance(var, ReferenceVariable):
         return f"reference({ntype(var.type)})"
     if isinstance(var, LocalVariable):
-        return f"local_solc_variable({var.location})"
+        return f"local_solc_variable({ntype(var.type)},{var.location})"
     if isinstance(var, StateVariable):
-        return f"state_solc_variable({ntype(var.type)})"
+        if not (var.is_constant or var.is_immutable):
+            try:
+                slot, _ = var.contract.compilation_unit.storage_layout_of(var.contract, var)
+            except KeyError:
+                slot = var.name
+        else:
+            slot = var.name
+        return f"state_solc_variable({ntype(var.type)},{slot})"
     if isinstance(var, LocalVariableInitFromTuple):
         return "local_variable_init_tuple"
     if isinstance(var, TupleVariable):