internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: crytic/slither

Issue:
ABIEncoderV2 flagged as solidity version
The following Solidity code is flagged as being different solidity versions:

```sol
pragma solidity 0.5.12;
pragma experimental ABIEncoderV2;
```

Outputs:

```
INFO:Detectors:
Different versions of Solidity is used in :
	- Version used: ['0.5.12', 'ABIEncoderV2']
	- 0.5.12 (Contract.sol#1)
	- ABIEncoderV2 (Contract.sol#2)
```


Discussion:
Hi @emilbayes, thank you for reporting this. We will fix it soon

Resolving patch:
diff --git a/slither/core/declarations/pragma_directive.py b/slither/core/declarations/pragma_directive.py
--- a/slither/core/declarations/pragma_directive.py
+++ b/slither/core/declarations/pragma_directive.py
@@ -21,5 +21,11 @@ def version(self):
     def name(self):
         return self.version
 
+    @property
+    def is_solidity_version(self):
+        if len(self._directive) > 0:
+            return self._directive[0].lower() == 'solidity'
+        return False
+
     def __str__(self):
         return 'pragma '+''.join(self.directive)
diff --git a/slither/detectors/attributes/constant_pragma.py b/slither/detectors/attributes/constant_pragma.py
--- a/slither/detectors/attributes/constant_pragma.py
+++ b/slither/detectors/attributes/constant_pragma.py
@@ -26,7 +26,7 @@ class ConstantPragma(AbstractDetector):
     def _detect(self):
         results = []
         pragma = self.slither.pragma_directives
-        versions = [p.version for p in pragma]
+        versions = [p.version for p in pragma if p.is_solidity_version]
         versions = sorted(list(set(versions)))
 
         if len(versions) > 1:


Test patch:
Repository: crytic/slither

Issue:
Fix embark and etherscan GH actions
- Embark fails on all our github actions (including crytic-compile) since ~1 month. The tests work locally, but it seems that some recent changes in the latest embark makes it fails on a CI
- Etherscan has now a constraint on the number of request per IP, which makes the CI fails from time to time. We need to add an API key to prevent it
Fix embark and etherscan GH actions
- Embark fails on all our github actions (including crytic-compile) since ~1 month. The tests work locally, but it seems that some recent changes in the latest embark makes it fails on a CI
- Etherscan has now a constraint on the number of request per IP, which makes the CI fails from time to time. We need to add an API key to prevent it


Discussion:

Resolving patch:
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -10,9 +10,9 @@
     python_requires='>=3.6',
     install_requires=['prettytable>=0.7.2',
                       'pysha3>=1.0.2',
-                      'crytic-compile>=0.1.6'],
-#                       'crytic-compile'],
-#    dependency_links=['git+https://github.com/crytic/crytic-compile.git@master#egg=crytic-compile'],
+#                      'crytic-compile>=0.1.6'],
+                       'crytic-compile'],
+    dependency_links=['git+https://github.com/crytic/crytic-compile.git@dev#egg=crytic-compile'],
     license='AGPL-3.0',
     long_description=open('README.md').read(),
     entry_points={


Test patch:
diff --git a/scripts/travis_test_embark.sh b/scripts/travis_test_embark.sh
--- a/scripts/travis_test_embark.sh
+++ b/scripts/travis_test_embark.sh
@@ -9,9 +9,8 @@ curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.34.0/install.sh | b
 source ~/.nvm/nvm.sh
 nvm install 10.17.0
 nvm use 10.17.0
-npm --version
 
-npm install -g embark
+npm install -g embark@4.2.0
 embark demo
 cd embark_demo
 npm install
diff --git a/scripts/travis_test_etherscan.sh b/scripts/travis_test_etherscan.sh
--- a/scripts/travis_test_etherscan.sh
+++ b/scripts/travis_test_etherscan.sh
@@ -8,7 +8,7 @@ cd etherscan
 wget -O solc-0.4.25 https://github.com/ethereum/solidity/releases/download/v0.4.25/solc-static-linux
 chmod +x solc-0.4.25
 
-slither 0x7F37f78cBD74481E593F9C737776F7113d76B315 --solc "./solc-0.4.25"
+slither 0x7F37f78cBD74481E593F9C737776F7113d76B315 --solc "./solc-0.4.25" --etherscan-apikey $GITHUB_ETHERSCAN
 
 if [ $? -ne 5 ]
 then
@@ -16,7 +16,7 @@ then
     exit -1
 fi
 
-slither rinkeby:0xFe05820C5A92D9bc906D4A46F662dbeba794d3b7 --solc "./solc-0.4.25"
+slither rinkeby:0xFe05820C5A92D9bc906D4A46F662dbeba794d3b7 --solc "./solc-0.4.25" --etherscan-apikey $GITHUB_ETHERSCAN
 
 if [ $? -ne 70 ]
 then
Repository: crytic/slither

Issue:
Add support for abi.decode on arrays
Ex:
```solidity
contract C{
        function f(bytes memory b) public{
                uint[2] memory m = abi.decode(b, (uint[2]));
        }
}
```



Discussion:

Resolving patch:
diff --git a/slither/visitors/slithir/expression_to_slithir.py b/slither/visitors/slithir/expression_to_slithir.py
--- a/slither/visitors/slithir/expression_to_slithir.py
+++ b/slither/visitors/slithir/expression_to_slithir.py
@@ -3,6 +3,8 @@
 from slither.core.declarations import Function
 from slither.core.expressions import (AssignmentOperationType,
                                       UnaryOperationType)
+from slither.core.solidity_types import ArrayType
+from slither.core.solidity_types.type import Type
 from slither.slithir.operations import (Assignment, Binary, BinaryType, Delete,
                                         Index, InitArray, InternalCall, Member,
                                         NewArray, NewContract,
@@ -173,6 +175,14 @@ def _post_identifier(self, expression):
     def _post_index_access(self, expression):
         left = get(expression.expression_left)
         right = get(expression.expression_right)
+        # Left can be a type for abi.decode(var, uint[2])
+        if isinstance(left, Type):
+            # Nested type are not yet supported by abi.decode, so the assumption
+            # Is that the right variable must be a constant
+            assert isinstance(right, Constant)
+            t = ArrayType(left, right.value)
+            set_val(expression, t)
+            return
         val = ReferenceVariable(self._node)
         # access to anonymous array
         # such as [0,1][x]


Test patch:
Repository: crytic/slither

Issue:
Add support for interfaceId 
0.6.7 introduced a new element: `interfaceId`
Add support for interfaceId 
0.6.7 introduced a new element: `interfaceId`


Discussion:

Resolving patch:
diff --git a/slither/slithir/convert.py b/slither/slithir/convert.py
--- a/slither/slithir/convert.py
+++ b/slither/slithir/convert.py
@@ -378,6 +378,19 @@ def _convert_type_contract(ir, slither):
         assignment.set_node(ir.node)
         assignment.lvalue.set_type(ElementaryType('bytes'))
         return assignment
+    if ir.variable_right == 'interfaceId':
+        entry_points = contract.functions_entry_points
+        interfaceId = 0
+        for entry_point in entry_points:
+            interfaceId = interfaceId ^ get_function_id(entry_point.full_name)
+        assignment = Assignment(ir.lvalue,
+                                Constant(str(interfaceId), type=ElementaryType('bytes4')),
+                                ElementaryType('bytes4'))
+        assignment.set_expression(ir.expression)
+        assignment.set_node(ir.node)
+        assignment.lvalue.set_type(ElementaryType('bytes4'))
+        return assignment
+
     if ir.variable_right == 'name':
         assignment = Assignment(ir.lvalue,
                                 Constant(contract.name),


Test patch:
Repository: crytic/slither

Issue:
Suicidal detector fails on external functions
If the [example](https://github.com/crytic/slither/wiki/Detector-Documentation#suicidal) function for the suicidal detector is changed from `public` to `external` the issue is no longer flagged.

```
pragma solidity ^0.5.0;
contract Suicidal{
    function kill() external{
        selfdestruct(msg.sender);
    }
}
```

`slither --version`: 0.6.12
`solc --version`: 0.5.15
Suicidal detector fails on external functions
If the [example](https://github.com/crytic/slither/wiki/Detector-Documentation#suicidal) function for the suicidal detector is changed from `public` to `external` the issue is no longer flagged.

```
pragma solidity ^0.5.0;
contract Suicidal{
    function kill() external{
        selfdestruct(msg.sender);
    }
}
```

`slither --version`: 0.6.12
`solc --version`: 0.5.15


Discussion:
Hi @wolflo,

Thank you for reporting this. I agree that external functions should be included in this detector, we will include them.
Hi @wolflo,

Thank you for reporting this. I agree that external functions should be included in this detector, we will include them.

Resolving patch:
diff --git a/slither/detectors/functions/suicidal.py b/slither/detectors/functions/suicidal.py
--- a/slither/detectors/functions/suicidal.py
+++ b/slither/detectors/functions/suicidal.py
@@ -46,7 +46,7 @@ def detect_suicidal_func(func):
         if func.is_constructor:
             return False
 
-        if func.visibility != 'public':
+        if func.visibility not in ['public', 'external']:
             return False
 
         calls = [c.name for c in func.internal_calls]
@@ -60,7 +60,7 @@ def detect_suicidal_func(func):
 
     def detect_suicidal(self, contract):
         ret = []
-        for f in [f for f in contract.functions if f.contract_declarer == contract]:
+        for f in contract.functions_declared:
             if self.detect_suicidal_func(f):
                 ret.append(f)
         return ret


Test patch:
Repository: crytic/slither

Issue:
Crash on nested try/catch if/then/else
```solidity
interface I{
    function f() external returns(bool);
}

contract C{
    function f(I i) public returns(bool){
        bool fail;
        try i.f() returns (bool success){
            if(success){
                fail = false;
            }
            else{
                fail = true;
            }
        } catch Error(string memory reason){
            fail = true; 
        }
        if(fail){
            return fail;
        }   
    }
}   
```

Related: https://github.com/crytic/slither/issues/511
Crash on nested try/catch if/then/else
```solidity
interface I{
    function f() external returns(bool);
}

contract C{
    function f(I i) public returns(bool){
        bool fail;
        try i.f() returns (bool success){
            if(success){
                fail = false;
            }
            else{
                fail = true;
            }
        } catch Error(string memory reason){
            fail = true; 
        }
        if(fail){
            return fail;
        }   
    }
}   
```

Related: https://github.com/crytic/slither/issues/511


Discussion:

Resolving patch:
diff --git a/slither/solc_parsing/declarations/function.py b/slither/solc_parsing/declarations/function.py
--- a/slither/solc_parsing/declarations/function.py
+++ b/slither/solc_parsing/declarations/function.py
@@ -995,7 +995,8 @@ def _fix_catch(self, node: Node, end_node: Node):
             link_nodes(node, end_node)
         else:
             for son in node.sons:
-                self._fix_catch(son, end_node)
+                if son != end_node:
+                    self._fix_catch(son, end_node)
 
     def _add_param(self, param: Dict) -> LocalVariableSolc:
 


Test patch:
Repository: crytic/slither

Issue:
Wrong tuple assignment
```
pragma solidity 0.5.0;


contract TuplePoc {

    mapping(address => uint256) public lastWithdrawTime;
    mapping(address => uint256) public balances;


    function withdrawFunds (uint amount) public {
        (bool success, bytes memory data) = msg.sender.call.value(amount)("");
        require(success);
        balances[msg.sender] -= amount;
        lastWithdrawTime[msg.sender] = now;
    }
 }

```
The generated IR for the above smart contract follows:

```
TUPLE_0(bool) = LOW_LEVEL_CALL, dest:msg.sender, function:call, arguments:[''] value:amount 
success = UNPACK TUPLE_0 index: 0 
data = UNPACK TUPLE_0 index: 1 
```
The above generated IR wrongly generates tuple assignments. The returned value for the low-level call in the source code contains a tuple of two variables. But, but the generated IR contains only one variable. 

Wrong tuple assignment
```
pragma solidity 0.5.0;


contract TuplePoc {

    mapping(address => uint256) public lastWithdrawTime;
    mapping(address => uint256) public balances;


    function withdrawFunds (uint amount) public {
        (bool success, bytes memory data) = msg.sender.call.value(amount)("");
        require(success);
        balances[msg.sender] -= amount;
        lastWithdrawTime[msg.sender] = now;
    }
 }

```
The generated IR for the above smart contract follows:

```
TUPLE_0(bool) = LOW_LEVEL_CALL, dest:msg.sender, function:call, arguments:[''] value:amount 
success = UNPACK TUPLE_0 index: 0 
data = UNPACK TUPLE_0 index: 1 
```
The above generated IR wrongly generates tuple assignments. The returned value for the low-level call in the source code contains a tuple of two variables. But, but the generated IR contains only one variable. 



Discussion:

Resolving patch:
diff --git a/slither/visitors/slithir/expression_to_slithir.py b/slither/visitors/slithir/expression_to_slithir.py
--- a/slither/visitors/slithir/expression_to_slithir.py
+++ b/slither/visitors/slithir/expression_to_slithir.py
@@ -115,11 +115,14 @@ def _post_assignement_operation(self, expression):
                 set_val(expression, None)
             else:
                 assert isinstance(right, TupleVariable)
+                tuple_types = []
                 for idx in range(len(left)):
                     if not left[idx] is None:
                         operation = Unpack(left[idx], right, idx)
                         operation.set_expression(expression)
+                        tuple_types.append(left[idx].type)
                         self._result.append(operation)
+                right.set_type(tuple_types)
                 set_val(expression, None)
         else:
             # Init of array, like


Test patch:
Repository: crytic/slither

Issue:
Set Solidity version for emitted contracts in `slither-flat`
Problem: Right now it seems like `slither-flat` has the ability to align Solidity versions across contract files. In some cases, it may make sense to automatically push the contract version to the latest major version, for example, from `0.5.8` to `0.5.16`.

Proposal would be to introduce a flag for `slither-flat` that can help set the pragma to be used for the contracts, e.g.,

```
slither-flat --pragma="^0.5.16" ... # I'm sure there's a nicer syntax :)
```
Set Solidity version for emitted contracts in `slither-flat`
Problem: Right now it seems like `slither-flat` has the ability to align Solidity versions across contract files. In some cases, it may make sense to automatically push the contract version to the latest major version, for example, from `0.5.8` to `0.5.16`.

Proposal would be to introduce a flag for `slither-flat` that can help set the pragma to be used for the contracts, e.g.,

```
slither-flat --pragma="^0.5.16" ... # I'm sure there's a nicer syntax :)
```


Discussion:

Resolving patch:
diff --git a/slither/tools/flattening/__main__.py b/slither/tools/flattening/__main__.py
--- a/slither/tools/flattening/__main__.py
+++ b/slither/tools/flattening/__main__.py
@@ -76,6 +76,10 @@ def parse_args():
         "--remove-assert", help="Remove call to assert().", action="store_true"
     )
 
+    group_patching.add_argument(
+        "--pragma-solidity", help="Set the solidity pragma with a given version.", action="store", default=None
+    )
+
     # Add default arguments from crytic-compile
     cryticparser.init(parser)
 
@@ -96,6 +100,7 @@ def main():
         remove_assert=args.remove_assert,
         private_to_internal=args.convert_private,
         export_path=args.dir,
+        pragma_solidity=args.pragma_solidity
     )
 
     try:
diff --git a/slither/tools/flattening/flattening.py b/slither/tools/flattening/flattening.py
--- a/slither/tools/flattening/flattening.py
+++ b/slither/tools/flattening/flattening.py
@@ -43,6 +43,7 @@ def __init__(
         remove_assert=False,
         private_to_internal=False,
         export_path: Optional[str] = None,
+        pragma_solidity: Optional[str] = None
     ):
         self._source_codes: Dict[Contract, str] = {}
         self._slither = slither
@@ -50,6 +51,7 @@ def __init__(
         self._remove_assert = remove_assert
         self._use_abi_encoder_v2 = False
         self._private_to_internal = private_to_internal
+        self._pragma_solidity = pragma_solidity
 
         self._export_path: Path = DEFAULT_EXPORT_PATH if export_path is None else Path(export_path)
 
@@ -165,8 +167,11 @@ def _pragmas(self) -> str:
         :return:
         """
         ret = ""
-        if self._slither.solc_version:
+        if self._pragma_solidity:
+            ret += f"pragma solidity {self._pragma_solidity};\n"
+        elif self._slither.solc_version:
             ret += f"pragma solidity {self._slither.solc_version};\n"
+
         if self._use_abi_encoder_v2:
             ret += "pragma experimental ABIEncoderV2;\n"
         return ret


Test patch:
Repository: crytic/slither

Issue:
Incorrect add of Phi operation on loop with dupplicate variable
Somewhere we introduced a bug on loop parsing between `0.6.12` and `master`:
```solidity
contract C{
    
    function f() public{
        if(true){
            for(uint index = 0;index<10;index ++){
            }
        }   
        else{
           for(uint index = 0;index<10;index ++){
           }
        }  
    }   
    
}   
```

```
core/cfg/node.py", line 811, in add_phi_origin_local_variable
    assert v == variable
AssertionError
```
Incorrect add of Phi operation on loop with dupplicate variable
Somewhere we introduced a bug on loop parsing between `0.6.12` and `master`:
```solidity
contract C{
    
    function f() public{
        if(true){
            for(uint index = 0;index<10;index ++){
            }
        }   
        else{
           for(uint index = 0;index<10;index ++){
           }
        }  
    }   
    
}   
```

```
core/cfg/node.py", line 811, in add_phi_origin_local_variable
    assert v == variable
AssertionError
```


Discussion:

Resolving patch:
diff --git a/slither/solc_parsing/declarations/function.py b/slither/solc_parsing/declarations/function.py
--- a/slither/solc_parsing/declarations/function.py
+++ b/slither/solc_parsing/declarations/function.py
@@ -148,11 +148,13 @@ def _add_local_variable(
         # Use of while in case of collision
         # In the worst case, the name will be really long
         if local_var_parser.underlying_variable.name:
-            while local_var_parser.underlying_variable.name in self._function.variables:
+            known_variables = [v.name for v in self._function.variables]
+            while local_var_parser.underlying_variable.name in known_variables:
                 local_var_parser.underlying_variable.name += "_scope_{}".format(
                     self._counter_scope_local_variables
                 )
                 self._counter_scope_local_variables += 1
+                known_variables = [v.name for v in self._function.variables]
         if local_var_parser.reference_id is not None:
             self._variables_renamed[local_var_parser.reference_id] = local_var_parser
         self._function.variables_as_dict[


Test patch:
Repository: crytic/slither

Issue:
function-id not zero-padding function signature 
```
ERC20:
+---------------------------------------+------------+
|                  Name                 |     ID     |
+---------------------------------------+------------+
|             totalSupply()             | 0x18160ddd |
|           balanceOf(address)          | 0x70a08231 |
|       allowance(address,address)      | 0xdd62ed3e |
|       transfer(address,uint256)       | 0xa9059cbb |
| transferFrom(address,address,uint256) | 0x23b872dd |
|        approve(address,uint256)       | 0x95ea7b3  |
+---------------------------------------+------------+

```

It's a minor annoyance, but for approve it outputs `0x95ea7b3` instead of `0x095ea7b3`. It is the same numerically, of course, but the function signature is more of an opaque 4-byte identifier than something numerically quantified.


function-id not zero-padding function signature 
```
ERC20:
+---------------------------------------+------------+
|                  Name                 |     ID     |
+---------------------------------------+------------+
|             totalSupply()             | 0x18160ddd |
|           balanceOf(address)          | 0x70a08231 |
|       allowance(address,address)      | 0xdd62ed3e |
|       transfer(address,uint256)       | 0xa9059cbb |
| transferFrom(address,address,uint256) | 0x23b872dd |
|        approve(address,uint256)       | 0x95ea7b3  |
+---------------------------------------+------------+

```

It's a minor annoyance, but for approve it outputs `0x95ea7b3` instead of `0x095ea7b3`. It is the same numerically, of course, but the function signature is more of an opaque 4-byte identifier than something numerically quantified.




Discussion:
Hi @epheph, thanks for reporting this.

It's a good suggestion, we will update the printer
Hi @epheph, thanks for reporting this.

It's a good suggestion, we will update the printer

Resolving patch:
diff --git a/slither/printers/summary/function_ids.py b/slither/printers/summary/function_ids.py
--- a/slither/printers/summary/function_ids.py
+++ b/slither/printers/summary/function_ids.py
@@ -27,11 +27,13 @@ def output(self, _filename):
             table = MyPrettyTable(['Name', 'ID'])
             for function in contract.functions:
                 if function.visibility in ['public', 'external']:
-                    table.add_row([function.solidity_signature, hex(get_function_id(function.solidity_signature))])
+                    function_id = get_function_id(function.solidity_signature)
+                    table.add_row([function.solidity_signature, f"{function_id:#0{10}x}"])
             for variable in contract.state_variables:
                 if variable.visibility in ['public']:
                     sig = variable.function_name
-                    table.add_row([sig, hex(get_function_id(sig))])
+                    function_id = get_function_id(sig)
+                    table.add_row([sig, f"{function_id:#0{10}x}"])
             txt += str(table) + '\n'
             all_tables.append((contract.name, table))
 


Test patch:
Repository: crytic/slither

Issue:
Expression not parsed IndexRangeAccess
I am getting `Expression not parsed IndexRangeAccess` error, I am assuming this is due to my use of the [array slices](https://solidity.readthedocs.io/en/v0.6.0/types.html#array-slices)?


Discussion:
Hi @petejkim, thank you for reporting this.

We will add the support for array slices soon.

Resolving patch:
diff --git a/slither/solc_parsing/expressions/expression_parsing.py b/slither/solc_parsing/expressions/expression_parsing.py
--- a/slither/solc_parsing/expressions/expression_parsing.py
+++ b/slither/solc_parsing/expressions/expression_parsing.py
@@ -763,4 +763,13 @@ def parse_expression(expression: Dict, caller_context: CallerContext) -> "Expres
         call.set_offset(src, caller_context.slither)
         return call
 
+    elif name == "IndexRangeAccess":
+        # For now, we convert array slices to a direct array access
+        # As a result the generated IR will lose the slices information
+        # As far as I understand, array slice are only used in abi.decode
+        # https://solidity.readthedocs.io/en/v0.6.12/types.html
+        # TODO: Investigate array slices usage and implication for the IR
+        base = parse_expression(expression["baseExpression"], caller_context)
+        return base
+
     raise ParsingError("Expression not parsed %s" % name)


Test patch: