Repository: crytic/slither

Issue:
Bug in variable-order printer
Hi there!

I was testing `variable-order` printer and found the following. Consider there are base contract and derived one and they both have variables with the same name. Thus, the derived contract has two state variables, but Slither does not indicate it. Example contract:
```
pragma solidity 0.4.25;

contract BaseContract {
    address internal owner;

    constructor() public {
        owner = msg.sender;
    }
    
    function ownerBase() public view returns (address) {
        return owner;
    }
    
}

contract DerivedContract is BaseContract {
    address public owner;

    function owners() public view returns (address, address) {
        return (owner, super.ownerBase());
    }

}
```

Slither output:
```
$ slither DerivedContract.sol --print variable-order
INFO:Printers:
DerivedContract:
+-------+---------+
|  Name |   Type  |
+-------+---------+
| owner | address |
+-------+---------+

INFO:Slither:DerivedContract.sol analyzed (2 contracts)
```


Discussion:
Hi @sobolev-igor, it's a good catch! thank you for reporting the issue, we are going to investigate how to fix it.

Resolving patch:
diff --git a/slither/core/declarations/contract.py b/slither/core/declarations/contract.py
--- a/slither/core/declarations/contract.py
+++ b/slither/core/declarations/contract.py
@@ -33,6 +33,7 @@ def __init__(self):
         self._structures = {}
         self._events = {}
         self._variables = {}
+        self._variables_ordered = [] # contain also shadowed variables
         self._modifiers = {}
         self._functions = {}
 
@@ -196,6 +197,13 @@ def state_variables(self):
         '''
         return list(self._variables.values())
 
+    @property
+    def state_variables_ordered(self):
+        '''
+            list(StateVariable): List of the state variables by order of declaration. Contains also shadowed variables
+        '''
+        return list(self._variables_ordered)
+
     @property
     def state_variables_inherited(self):
         '''
diff --git a/slither/printers/summary/variable_order.py b/slither/printers/summary/variable_order.py
--- a/slither/printers/summary/variable_order.py
+++ b/slither/printers/summary/variable_order.py
@@ -23,9 +23,9 @@ def output(self, _filename):
         for contract in self.slither.contracts_derived:
             txt += '\n{}:\n'.format(contract.name)
             table = PrettyTable(['Name', 'Type'])
-            for variable in contract.state_variables:
+            for variable in contract.state_variables_ordered:
                 if not variable.is_constant:
-                    table.add_row([variable.name, str(variable.type)])
+                    table.add_row([variable.canonical_name, str(variable.type)])
             txt += str(table) + '\n'
 
         self.info(txt)
diff --git a/slither/solc_parsing/declarations/contract.py b/slither/solc_parsing/declarations/contract.py
--- a/slither/solc_parsing/declarations/contract.py
+++ b/slither/solc_parsing/declarations/contract.py
@@ -222,6 +222,7 @@ def parse_structs(self):
     def parse_state_variables(self):
         for father in self.inheritance_reverse:
             self._variables.update(father.variables_as_dict())
+            self._variables_ordered += father.state_variables_ordered
 
         for varNotParsed in self._variablesNotParsed:
             var = StateVariableSolc(varNotParsed)
@@ -229,6 +230,7 @@ def parse_state_variables(self):
             var.set_contract(self)
 
             self._variables[var.name] = var
+            self._variables_ordered.append(var)
 
     def _parse_modifier(self, modifier):
 


Test patch: