Repository: pessimistic-io/slitherin (language: python)

Issue:
fix: failing on immutable contract reference call 
Hi!

That solidity code:
```solidity
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.19;

interface IERC20 {
    function transferFrom(address from, address to, uint256 amount) external returns (bool);
}

contract Test
{
    IERC20 immutable TOKEN = IERC20(address(0));
    function test() internal {
        TOKEN.transferFrom(address(this), address(0), 0);
    }
}
```

would crash nft_approve_warning with next traceback:

```traceback
…
  File "/home/y/work/pessimistic/slitherin/slither_pess/detectors/nft_approve_warning.py", line 65, in _detect                                                                                 
    for d in self._detect_arbitrary_from(f):                                                                                                                                                   
  File "/home/y/work/pessimistic/slitherin/slither_pess/detectors/nft_approve_warning.py", line 38, in _detect_arbitrary_from                                                                  
    return self._arbitrary_from(f.nodes)                                                                                                                                                       
  File "/home/y/work/pessimistic/slitherin/slither_pess/detectors/nft_approve_warning.py", line 50, in _arbitrary_from                                                                         
    and hasattr(ir.function, 'solidity_signature')                                                                                                                                             
AttributeError: 'TypeConversion' object has no attribute 'function'
```

I made a very simple fix!


Discussion / hints:

Fix patch:
diff --git a/.gitignore b/.gitignore
index 48ed8ca..7c9c532 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,7 @@
 .DS_Store
 *.egg-info
-__pycache__
+**/__pycache__/
 build/
 dist/
-.slither-pess/
\ No newline at end of file
+.slither-pess/
+node_modules/
\ No newline at end of file
diff --git a/README.md b/README.md
index 9471fec..f12d05a 100644
--- a/README.md
+++ b/README.md
@@ -29,7 +29,7 @@ Please let us know if you have discovered an [issue/bug/vulnerability](https://t
 | Enhancements & New Detectors | [Project Improvements](https://github.com/pessimistic-io/slitherin#enhancements--new-detectors)               |
 
 ## Installation Process
-
+### Using Git
 To install Pessimistic Detectors: 
 1. Install the [original Slither](https://github.com/crytic/slither#how-to-install);
 2. Clone our repository;
@@ -38,11 +38,18 @@ To install Pessimistic Detectors:
 python3 setup.py develop
 ```
 > Keep in mind that you don't have to reinstall the plugin after changes in the repository!
-4. Run original Slither as usual.
+4. Run the original Slither as usual.
 5. Dependencies must be installed in order to test the detectors on our test contracts:
 ```bash
 npm install
 ```
+### Using Pip
+1. Install the [original Slither](https://github.com/crytic/slither#how-to-install);
+2. Install the pip [package](https://pypi.org/project/slitherin/):
+```bash
+pip install slitherin
+```
+3. Run the original Slither as usual.
 
 ## **Detectors Table**
 
@@ -53,23 +60,24 @@ npm install
 | [TX Gasprice Warning](https://github.com/pessimistic-io/slitherin/blob/master/slither_pess/detectors/tx_gasprice_warning.py)                              | [Explore](https://github.com/pessimistic-io/slitherin/blob/master/docs/tx_gasprice_warning.md)                   | [Test](https://github.com/pessimistic-io/slitherin/blob/master/tests/tx_gasprice_warning_test.sol)                                                        | 0                                                                                                                |
 | [UniswapV2 Integration](https://github.com/pessimistic-io/slitherin/blob/master/slither_pess/detectors/uni_v2.py)                                         | [Explore](https://github.com/pessimistic-io/slitherin/blob/master/docs/integration_uniswapV2.md)                 | [Test](https://github.com/pessimistic-io/slitherin/blob/master/tests/Bad_UniswapV2_test.sol)                                                              | 0                                                                                                                |
 | [Token Fallback](https://github.com/pessimistic-io/slitherin/blob/master/slither_pess/detectors/token_fallback.py)                                        | [Explore](https://github.com/pessimistic-io/slitherin/blob/master/docs/token_fallback.md)                        | [Test](https://github.com/pessimistic-io/slitherin/blob/master/tests/token_fallback_test.sol)                                                             | 0                                                                                                                |
-| [Timelock Controller](https://github.com/pessimistic-io/slitherin/blob/master/slither_pess/detectors/timelock_controller.py)                              | [Explore](https://github.com/pessimistic-io/slitherin/blob/master/docs/timelock_controller.md)                   | [Test](https://github.com/pessimistic-io/slitherin/blob/master/tests/timelock_controller_test.sol)                                                        | 0                                                                                                                |
+| [Timelock Controller](https://github.com/pessimistic-io/slitherin/blob/master/slither_pess/detectors/timelock_controller.py)                              | [Explore](https://github.com/pessimistic-io/slitherin/blob/master/docs/timelock_controller.md)                   | [Test](https://github.com/pessimistic-io/slitherin/blob/master/tests/timelock_controller_test.sol)                                                        | 1                                                                                                                |
 | [Strange Setter](https://github.com/pessimistic-io/slitherin/blob/master/slither_pess/detectors/strange_setter.py)                                        | [Explore](https://github.com/pessimistic-io/slitherin/blob/master/docs/strange_setter.md)                        | [Test](https://github.com/pessimistic-io/slitherin/blob/master/tests/strange_setter_test.sol)                                                             | 0                                                                                                                |
 | [Read-only Reentrancy](https://github.com/pessimistic-io/slitherin/blob/master/slither_pess/detectors/read_only_reentrancy.py)                            | [Explore](https://github.com/pessimistic-io/slitherin/blob/master/docs/readonly_reentrancy.md)                   | [Test](https://github.com/pessimistic-io/slitherin/blob/master/tests/readonly_reentrancy_test.sol)                                                        | 0                                                                                                                |
 | [NFT Approve Warning](https://github.com/pessimistic-io/slitherin/blob/master/slither_pess/detectors/nft_approve_warning.py)                              | [Explore](https://github.com/pessimistic-io/slitherin/blob/master/docs/nft_approve_warning.md)                   | [Test](https://github.com/pessimistic-io/slitherin/blob/master/tests/nft_approve_warning_test.sol)                                                        | 0                                                                                                                |
-| [Multiple Storage Read](https://github.com/pessimistic-io/slitherin/blob/master/slither_pess/detectors/multiple_storage_read.py)                          | [Explore](https://github.com/pessimistic-io/slitherin/blob/master/docs/multiple_storage_read.md)                 | [Test](https://github.com/pessimistic-io/slitherin/blob/master/tests/multiple_storage_read_test.sol)                                                      | 6                                                                                                                |
+| [Multiple Storage Read](https://github.com/pessimistic-io/slitherin/blob/master/slither_pess/detectors/multiple_storage_read.py)                          | [Explore](https://github.com/pessimistic-io/slitherin/blob/master/docs/multiple_storage_read.md)                 | [Test](https://github.com/pessimistic-io/slitherin/blob/master/tests/multiple_storage_read_test.sol)                                                      | 9                                                                                                                |
 | [Magic Number](https://github.com/pessimistic-io/slitherin/blob/master/slither_pess/detectors/magic_number.py)                                            | [Explore](https://github.com/pessimistic-io/slitherin/blob/master/docs/magic_number.md)                          | [Test](https://github.com/pessimistic-io/slitherin/blob/master/tests/magic_number_test.sol)                                                               | 3                                                                                                                |
 | [Inconsistent Non-Reentrant](https://github.com/pessimistic-io/slitherin/blob/master/slither_pess/detectors/inconsistent_nonreentrant.py)                 | [Explore](https://github.com/pessimistic-io/slitherin/blob/master/docs/inconsistent_nonreentrant.md)             | [Test](https://github.com/pessimistic-io/slitherin/blob/master/tests/inconsistent_nonreentrant_test.sol)                                                  | 0                                                                                                                |
 | [Falsy Only EOA Modifier](https://github.com/pessimistic-io/slitherin/blob/master/slither_pess/detectors/falsy_only_eoa_modifier.py)                      | [Explore](https://github.com/pessimistic-io/slitherin/blob/master/docs/falsy_only_eoa_modifier.md)               | [Test](https://github.com/pessimistic-io/slitherin/blob/master/tests/falsy_only_eoa_modifier_test.sol)                                                    | 0                                                                                                                |
-| [Missing Event Setter](https://github.com/pessimistic-io/slitherin/blob/master/slither_pess/detectors/event_setter.py)                                    | [Explore](https://github.com/pessimistic-io/slitherin/blob/master/docs/event_setter.md)                          | [Test](https://github.com/pessimistic-io/slitherin/blob/master/tests/event_setter_test.sol)                                                               | 0                                                                                                                |
+| [Missing Event Setter](https://github.com/pessimistic-io/slitherin/blob/master/slither_pess/detectors/event_setter.py)                                    | [Explore](https://github.com/pessimistic-io/slitherin/blob/master/docs/event_setter.md)                          | [Test](https://github.com/pessimistic-io/slitherin/blob/master/tests/event_setter_test.sol)                                                               | 1                                                                                                                |
 | [Dubious Typecast](https://github.com/pessimistic-io/slitherin/blob/master/slither_pess/detectors/dubious_typecast.py)                                    | [Explore](https://github.com/pessimistic-io/slitherin/blob/master/docs/dubious_typecast.md)                      | [Test](https://github.com/pessimistic-io/slitherin/blob/master/tests/dubious_typecast_test.sol)                                                           | 0                                                                                                                |
 | [Double Entry Token Possibility](https://github.com/pessimistic-io/slitherin/blob/master/slither_pess/detectors/double_entry_token_possibility.py)        | [Explore](https://github.com/pessimistic-io/slitherin/blob/master/docs/double_entry_token_possibility.md)        | In progress                                                                                                                                               | 0                                                                                                                |
 | [Call Forward To Protected](https://github.com/pessimistic-io/slitherin/blob/master/slither_pess/detectors/call_forward_to_protected.py)                  | [Explore](https://github.com/pessimistic-io/slitherin/blob/master/docs/call_forward_to_protected.md)             | [Test](https://github.com/pessimistic-io/slitherin/blob/master/tests/call_forward_to_protected_test.sol)                                                  | 0                                                                                                                |
-| [Before Token Transfer](https://github.com/pessimistic-io/slitherin/blob/master/slither_pess/detectors/before_token_transfer.py)                          | [Explore](https://github.com/pessimistic-io/slitherin/blob/master/docs/before_token_transfer.md)                 | [Test](https://github.com/pessimistic-io/slitherin/blob/master/tests/before_token_transfer_test.sol)                                                      | 1                                                                                                                |
+| [Before Token Transfer](https://github.com/pessimistic-io/slitherin/blob/master/slither_pess/detectors/before_token_transfer.py)                          | [Explore](https://github.com/pessimistic-io/slitherin/blob/master/docs/before_token_transfer.md)                 | [Test](https://github.com/pessimistic-io/slitherin/blob/master/tests/before_token_transfer_test.sol)                                                      | 2                                                                                                                |
+| [For Continue Increment](https://github.com/pessimistic-io/slitherin/blob/master/slither_pess/detectors/for_continue_increment.py)                        | [Explore](https://github.com/pessimistic-io/slitherin/blob/master/docs/for_continue_increment.md)                 | [Test](https://github.com/pessimistic-io/slitherin/blob/master/tests/for_continue_increment.sol)                                                         | 0                                                                                                                |
 
 **Please note:**
 
-- *Valid - issues included in reports and fixed by developers (January 2023 - April 2023).
+- *Valid - issues included in reports and fixed by developers (January 2023 - June 2023).
 
 - There is one detector that is disabled by default: [pess-uni-v2](https://github.com/pessimistic-io/slitherin/blob/master/slither_pess/detectors/uni_v2.py). **It is recommended to run it only on projects that integrate [Uniswap V2](https://betterprogramming.pub/uniswap-v2-in-depth-98075c826254)!**
 
@@ -105,7 +113,7 @@ Prior to adding an *enhancement*, ensure that:
 | Fix - Readonly Reentrancy Detector                                                                                                    | Completed  |
 | Suggestion - Write a Walkthrough Article                                                                                              | Completed  |
 | Add [UniswapV2 Integration](https://github.com/pessimistic-io/slitherin/blob/master/slither_pess/detectors/uni_v2.py) detector        | Completed  |
-| For-continue-increment - add detector                                                                                                 | In progress|
+| For-continue-increment - add detector                                                                                                 | Completed  |
 | Refactor python code. Make it cleaner.                                                                                                | TODO       |
 | Nft-approve-warning detector - remove detection with "this" as a first parameter in "transferFrom()" function                         | TODO       |
 | Strange-setter detector - remove detection when mappings or structs are set                                                           | TODO       |
diff --git a/docs/dubious_typecast.md b/docs/dubious_typecast.md
index 186b4e9..1f94df4 100644
--- a/docs/dubious_typecast.md
+++ b/docs/dubious_typecast.md
@@ -1,18 +1,19 @@
 # Dubious Typecast
 
 ## Configuration
-* Check: `pess-dubious-typecast`
-* Severity: `Low`
-* Confidence: `Low` 
+
+- Check: `pess-dubious-typecast`
+- Severity: `Medium`
+- Confidence: `High`
 
 ## Description
-Highlights unstandard typecasts.
 
-### Potential Improvement
-Reduce the number of FP removing the highlight of OK typecasts.
+Highlights nonstandard typecasts. E.g: `uint256(uint8(K))`
 
 ## Vulnerable Scenario
+
 [test scenario](../tests/dubious_typecast_test.sol)
 
 ## Recommendation
-Makes contract logic more complex, which leads to an error probability increment. Use clean variables without typecasts.
\ No newline at end of file
+
+Verify that the typecast doesn't break the code.
diff --git a/docs/integration_uniswapV2.md b/docs/integration_uniswapV2.md
index a9a339c..a83647b 100644
--- a/docs/integration_uniswapV2.md
+++ b/docs/integration_uniswapV2.md
@@ -40,5 +40,10 @@ Checks the correctness of UniswapV2 integration in the contract.
 * Description - Pools must not allow deflationary (tokens that take fees for transfer) and elastic supply tokens which make arbitrage possible.
 * Recommendation - Do not use [deflationary](../utils/deflat_tokens.json) and [rebase](../utils/rebase_tokens.json) tokens in UniswapV2 integrations.
 
+### tainted-swap-routes
+* Impact - Medium;
+* Description - Looks for UniV2 funtions where the path parameter is partially or entirely provided from external invocation.
+* Recommendation - Do not use functions where path parameter is provided through customs invocations.
+
 ## Vulnerable Scenario
 [test scenario](../tests/Bad_UniswapV2_test.sol)
diff --git a/package-lock.json b/package-lock.json
index 0da369a..5e05519 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -5,20 +5,20 @@
   "packages": {
     "": {
       "dependencies": {
-        "@openzeppelin/contracts": "^4.8.2"
+        "@openzeppelin/contracts": "^4.9.2"
       }
     },
     "node_modules/@openzeppelin/contracts": {
-      "version": "4.8.2",
-      "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-4.8.2.tgz",
-      "integrity": "sha512-kEUOgPQszC0fSYWpbh2kT94ltOJwj1qfT2DWo+zVttmGmf97JZ99LspePNaeeaLhCImaHVeBbjaQFZQn7+Zc5g=="
+      "version": "4.9.2",
+      "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-4.9.2.tgz",
+      "integrity": "sha512-mO+y6JaqXjWeMh9glYVzVu8HYPGknAAnWyxTRhGeckOruyXQMNnlcW6w/Dx9ftLeIQk6N+ZJFuVmTwF7lEIFrg=="
     }
   },
   "dependencies": {
     "@openzeppelin/contracts": {
-      "version": "4.8.2",
-      "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-4.8.2.tgz",
-      "integrity": "sha512-kEUOgPQszC0fSYWpbh2kT94ltOJwj1qfT2DWo+zVttmGmf97JZ99LspePNaeeaLhCImaHVeBbjaQFZQn7+Zc5g=="
+      "version": "4.9.2",
+      "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-4.9.2.tgz",
+      "integrity": "sha512-mO+y6JaqXjWeMh9glYVzVu8HYPGknAAnWyxTRhGeckOruyXQMNnlcW6w/Dx9ftLeIQk6N+ZJFuVmTwF7lEIFrg=="
     }
   }
 }
diff --git a/package.json b/package.json
index ab74e50..ee90a8b 100644
--- a/package.json
+++ b/package.json
@@ -1,5 +1,5 @@
 {
   "dependencies": {
-    "@openzeppelin/contracts": "^4.8.2"
+    "@openzeppelin/contracts": "^4.9.2"
   }
 }
diff --git a/setup.py b/setup.py
index d2ce103..2236a25 100644
--- a/setup.py
+++ b/setup.py
@@ -1,14 +1,24 @@
 from setuptools import setup, find_packages
 
+with open("./README.md", "r") as f:
+    long_description = f.read()
+
 setup(
-    name="slither-pess",
-    description="Some pessimistic detectors",
+    name="slitherin",
+    description="Pessimistic security Slither detectors",
+    long_description=long_description,
+    long_description_content_type="text/markdown",
     url="https://github.com/pessimistic-io/slitherin",
-    author="Pessimistic",
-    version="0.1",
+    author="Pessimistic.io",
+    version="0.1.0",
+    package_dir={"":"."},
     packages=find_packages(),
+    license="AGPL-3.0",
     python_requires=">=3.8",
     install_requires=["slither-analyzer>=0.8.3"],
+    extras_requires={
+        "dev": ["twine>=4.0.2"],
+    },
     entry_points={
         "slither_analyzer.plugin": "slither my-plugin=slither_pess:make_plugin",
     },
diff --git a/slither_pess/detectors/__pycache__/__init__.cpython-38.pyc b/slither_pess/detectors/__pycache__/__init__.cpython-38.pyc
deleted file mode 100644
index aae9da7..0000000
Binary files a/slither_pess/detectors/__pycache__/__init__.cpython-38.pyc and /dev/null differ
diff --git a/slither_pess/detectors/__pycache__/double_entry_token_possibility.cpython-38.pyc b/slither_pess/detectors/__pycache__/double_entry_token_possibility.cpython-38.pyc
deleted file mode 100644
index 428511d..0000000
Binary files a/slither_pess/detectors/__pycache__/double_entry_token_possibility.cpython-38.pyc and /dev/null differ
diff --git a/slither_pess/detectors/__pycache__/nft_approve_warning.cpython-38.pyc b/slither_pess/detectors/__pycache__/nft_approve_warning.cpython-38.pyc
deleted file mode 100644
index e173652..0000000
Binary files a/slither_pess/detectors/__pycache__/nft_approve_warning.cpython-38.pyc and /dev/null differ
diff --git a/slither_pess/detectors/__pycache__/unprotected_setter.cpython-38.pyc b/slither_pess/detectors/__pycache__/unprotected_setter.cpython-38.pyc
deleted file mode 100644
index ed6a6e0..0000000
Binary files a/slither_pess/detectors/__pycache__/unprotected_setter.cpython-38.pyc and /dev/null differ
diff --git a/slither_pess/detectors/double_entry_token_possibility.py b/slither_pess/detectors/double_entry_token_possibility.py
index 10cc3bb..1e06834 100644
--- a/slither_pess/detectors/double_entry_token_possibility.py
+++ b/slither_pess/detectors/double_entry_token_possibility.py
@@ -22,9 +22,8 @@ class DoubleEntryTokenPossiblity(AbstractDetector):
     def get_tokens_as_params(self, fun):
 
         res = []  # параметры функции
-
         for p in fun.parameters:
-            if str(p.type) in ['IERC20[]', 'address[]']:
+            if len(p._name) and str(p.type) in ['IERC20[]', 'address[]']:
                 res.append(p)
 
         return res
diff --git a/slither_pess/detectors/dubious_typecast.py b/slither_pess/detectors/dubious_typecast.py
index ea781b0..27e6c7b 100644
--- a/slither_pess/detectors/dubious_typecast.py
+++ b/slither_pess/detectors/dubious_typecast.py
@@ -1,52 +1,116 @@
+from typing import List, Optional, Tuple
 from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
-from slither.slithir.operations import TypeConversion
+from slither.slithir.operations import TypeConversion, Operation
+from slither.core.declarations import FunctionContract
+from slither.core.cfg.node import Node
 
-def _getType(ir): # returns the last word of ir: "... type conversion to TYPENAME"
-    return str(ir).split(" ")[-1]
 
-def get_first_double_typecast_index(irs): # returns number
-    for i in range(1,len(irs)):
-        a=irs[i-1]
-        b=irs[i]
-        check = isinstance(a,TypeConversion) and isinstance(b, TypeConversion)
-        if check:
-            return i-1
-    return -1
+def is_ok_cast(from_type: str, to_type: str) -> bool:
+    if from_type == to_type:
+        return True
+    if from_type == "address" or to_type == "address":
+        # address <-> interface/contract/this
+        # address <-> uint160 (solidity doesn't allow other direct casts of address)
+        return True
+
+    if "bytes" in from_type and "bytes" in to_type:
+        # bytesX <-> bytesY will have different results
+        return False
+
+    if "bytes" in from_type or "bytes" in to_type:
+        return True
+
+    if "uint" == from_type[:4] and "uint" in to_type[:4]:
+        size_from = from_type[4:]
+        if size_from == "":
+            size_from = "256"
+
+        size_to = to_type[4:]
+        if to_type == "":
+            size_to = "256"
+
+        if int(size_from) > int(size_to):
+            return False
+        return True
+
+    if "int" == from_type[:3] and "int" == to_type[:3]:
+        size_from = from_type[3:]
+        if size_from == "":
+            size_from = "256"
+
+        size_to = to_type[3:]
+        if to_type == "":
+            size_to = "256"
+
+        if int(size_from) > int(size_to):
+            return False
+        return True
+
+    sorted_types = sorted([from_type, to_type])
+    if "int" == sorted_types[0][:3] and "uint" == sorted_types[1][:4]:
+        return False
+
+    return True
 
 
 class DubiousTypecast(AbstractDetector):
     """
-    Shows variables which are typecasted more than once.
+    Shows nonstandard typecasts.
     """
 
-    ARGUMENT = 'pess-dubious-typecast' # slither will launch the detector with slither.py --detect mydetector
-    HELP = 'uint8 = uint8(uint256)'
-    IMPACT = DetectorClassification.LOW
-    CONFIDENCE = DetectorClassification.LOW
-
-    WIKI = 'https://github.com/pessimistic-io/slitherin/blob/master/docs/dubious_typecast.md'
-    WIKI_TITLE = 'Dubious Typecast'
-    WIKI_DESCRIPTION = "Constant variables should not be typecasted more than once"
-    WIKI_EXPLOIT_SCENARIO = 'Makes contract logic more complex, wich leads to error probability increment and make integration more difficult'
-    WIKI_RECOMMENDATION = 'Use clear constants'
-
-    def getDT(self, fun, params=None):
-        res = []
-        for n in fun.nodes:
-            r = get_first_double_typecast_index(n.irs)
-            if r>-1:
-                res.append(_getType(n.irs[r+1])+'<='+_getType(n.irs[r]))
-        return res
+    ARGUMENT = "pess-dubious-typecast"  # slither will launch the detector with slither.py --detect mydetector
+    HELP = "uint8 = uint8(uint256)"
+    IMPACT = DetectorClassification.MEDIUM
+    CONFIDENCE = DetectorClassification.HIGH
+
+    WIKI = "https://github.com/pessimistic-io/slitherin/blob/master/docs/dubious_typecast.md"
+    WIKI_TITLE = "Dubious Typecast"
+    WIKI_DESCRIPTION = "Check docs"
+    WIKI_EXPLOIT_SCENARIO = (
+        "Can produce unpredictable results because of nonstandard typecasts"
+    )
+    WIKI_RECOMMENDATION = "Use clear constants"
+
+    def analyze_irs(self, irs: List[Operation]) -> List[Tuple[str, str]]:
+        results = []
+        for i in irs:
+            try:
+                if isinstance(i, TypeConversion):
+                    from_type = i.variable.type
+                    to_type = i.type
+
+                    if not (is_ok_cast(str(from_type), str(to_type))):
+                        results.append((from_type, to_type))
+            except Exception as e:
+                print("DubiousTypecast:Failed to check types", e)
+                print(i)
+
+        return results
+
+    def get_dubious_typecasts(self, fun: FunctionContract, params=None):
+        results: List[Tuple[Node, List[Tuple[str, str]]]] = []
+        for node in fun.nodes:
+            node_res = self.analyze_irs(node.irs)
+            if node_res:
+                results.append((node, node_res))
+        return results
 
     def _detect(self):
-        res = []
+        results = []
         for contract in self.compilation_unit.contracts_derived:
             for f in contract.functions:
-                x = self.getDT(f)
-                if x:
-                    for j in x:
-                        res.append(self.generate_result([
-                            'Function ',
-                            f, ' has a dubious typecast: ', j,
-                            '\n']))
-        return res
+                func_res = self.get_dubious_typecasts(f)
+                if func_res:
+                    info = ["Dubious typecast in ", f, ":\n"]
+                    for node, node_res in func_res:
+                        for from_type, to_type in node_res:
+                            info += [
+                                f"\t{str(from_type)} => {str(to_type)} casting occurs in ",
+                                node,
+                                "\n",
+                            ]
+                    res = self.generate_result(info)
+                    res.add(f)
+                    results.append(res)
+
+        return results
diff --git a/slither_pess/detectors/nft_approve_warning.py b/slither_pess/detectors/nft_approve_warning.py
index 754777e..8f17299 100644
--- a/slither_pess/detectors/nft_approve_warning.py
+++ b/slither_pess/detectors/nft_approve_warning.py
@@ -43,8 +43,11 @@ def _arbitrary_from(self, nodes: List[Node]):
         irList = []
         for node in nodes:
             for ir in node.irs:
-                if not hasattr(ir.function, 'solidity_signature'): continue
-                if (ir.function.solidity_signature in self._signatures):
+                if (
+                    hasattr(ir, 'function')
+                    and hasattr(ir.function, 'solidity_signature')
+                    and ir.function.solidity_signature in self._signatures
+                ):
                     is_from_sender = is_dependent(ir.arguments[0], SolidityVariableComposed("msg.sender"), node.function.contract)
                     # is_from_self = is_dependent(ir.arguments[0], SolidityVariable("this"), node.function.contract)
                     if (not is_from_sender): # and not is_from_self
@@ -59,4 +62,4 @@ def _detect(self):
             for f in c.functions:
                 for d in self._detect_arbitrary_from(f):
                     res.append(self.generate_result([f.contract_declarer.name, ' ',f.name, ' parameter from is not related to msg.sender ', d, '\n']))
-        return res
\ No newline at end of file
+        return res
diff --git a/slither_pess/detectors/strange_setter.py b/slither_pess/detectors/strange_setter.py
index 79961ab..3a8d321 100644
--- a/slither_pess/detectors/strange_setter.py
+++ b/slither_pess/detectors/strange_setter.py
@@ -31,9 +31,10 @@ def _is_strange_setter(self, fun: Function) -> bool:
                                 return False
         if isinstance(fun, Function):   # check for a correct function type
             for param in fun.parameters: 
-                for n in fun.nodes:
-                    if n.state_variables_written and str(param) in str(n):  # check if there's a state variable setter using function parameters
-                        return False
+                if fun.state_variables_written:
+                    for n in fun.nodes:
+                        if str(param) in str(n):
+                            return False
         return True
 
     def _is_strange_constructor(self, fun: Function) -> bool:
@@ -55,16 +56,17 @@ def _detect(self) -> List[Output]:
             if not contract.is_interface:
                 overriden_funtions = [] # functions that are overridden
                 for f in contract.functions:
-                    x = False
-                    overriden_funtions.append(contract.get_functions_overridden_by(f))  # adding functions to an overridden list
-                    if f.name == "constructor":
-                        x = self._is_strange_constructor(f)
-                    if f.name.startswith("set") and not f in overriden_funtions and len(f.nodes) != 0:  # check if setter starts with 'set', is not overriden and is not empty 
-                        x = self._is_strange_setter(f)
-                    if x:
-                        res.append(self.generate_result([
-                            "Function", ' ',
-                            f, ' is a strange setter. ',
-                            'Nothing is set in constructor or set in a function without using function parameters'
-                            '\n']))
+                    if f.parameters:
+                        x = False
+                        overriden_funtions.append(contract.get_functions_overridden_by(f))  # adding functions to an overridden list
+                        if f.name == "constructor":
+                            x = self._is_strange_constructor(f)
+                        if f.name.startswith("set") and not f in overriden_funtions and len(f.nodes) != 0:  # check if setter starts with 'set', is not overriden and is not empty 
+                            x = self._is_strange_setter(f)
+                        if x:
+                            res.append(self.generate_result([
+                                "Function", ' ',
+                                f, ' is a strange setter. ',
+                                'Nothing is set in constructor or set in a function without using function parameters'
+                                '\n']))
         return res
diff --git a/slither_pess/detectors/uni_v2.py b/slither_pess/detectors/uni_v2.py
index 7e4da47..9dfd840 100644
--- a/slither_pess/detectors/uni_v2.py
+++ b/slither_pess/detectors/uni_v2.py
@@ -1,13 +1,201 @@
 import sys
 import os
 import json
-from typing import List
+import copy
+from typing import List, Optional
 from slither.utils.output import Output
 from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
 from slither.core.declarations import Function, Contract
-from slither.slithir.operations.assignment import Assignment
 from slither.core.expressions.type_conversion import TypeConversion
+from slither.core.cfg.node import NodeType, Node
+from slither.core.variables.local_variable import LocalVariable
+from slither.core.solidity_types.array_type import ArrayType
+from slither.slithir.operations import SolidityCall, InternalCall, HighLevelCall
+from slither.slithir.operations.assignment import Assignment
+from slither.analyses.data_dependency.data_dependency import is_dependent
+
+
+class Context():
+  def __init__(self, c: Contract, entry_point: Function, func: Function, args_tainted_mask: List[bool], verbose: bool):
+    self.visited = []
+    self.contract = c
+    self.entry_point = entry_point
+    self.hit_function = None
+    self.tainted_path = []
+    self.param_name = None
+    self.function = func
+    self.args_tainted_mask = args_tainted_mask #TODO remove as this is redundant (covered by entrypoint_params_index_dependency)
+    self.entrypoint_params_index_dependency: List[List[int]] = [[i] for i in range(len(entry_point.parameters))]
+    self.call_chain = [entry_point.name]
+    self.hits = []
+    self.verb = verbose
+  
+  def make_copy(self): # to avoid passing by reference in internal calls inspections
+    cp = copy.copy(self)
+    cp.call_chain = copy.copy(self.call_chain)
+    cp.entrypoint_params_index_dependency = copy.copy(self.entrypoint_params_index_dependency)
+    return cp
+
+  def __str__(self): # debug
+    return 'entry_point' + str(self.entry_point) + 'hit_function' + str(self.hit_function) + 'param_name' + str(self.param_name) 
+
+class Hit():
+  def __init__(self, entry_point: Function, hit_function: Function, param_name, call_chain: List[str], entry_params_used: List[str], swap_func: str):
+    self.entry_point = entry_point
+    self.hit_function = hit_function
+    self.param_name = param_name
+    self.call_chain = call_chain
+    self.entry_params_used = entry_params_used
+    self.swap_func = swap_func
+
+swap_functions = ["swapExactTokensForTokens","swapTokensForExactTokens","swapExactTokensForTokensSupportingFeeOnTransferTokens","swapExactETHForTokensSupportingFeeOnTransferTokens",
+ "swapExactTokensForETHSupportingFeeOnTransferTokens","swapETHForExactTokens","swapExactTokensForETH","swapTokensForExactETH","swapExactETHForTokens", "getAmountsOut", "getAmountsIn"]
+swap_route_arg_pos = [2,2,2,1,2,1,2,2,1,1,1]       
+
+# widespread false positives
+banned_funcs = ["ensure", "constructor"]
+# partial (LIKE %x%)
+banned_funcs_partial = [] 
+banned_contracts_partial = ["swap", "dex", "router", "pancake", "buysell"] 
+  
+
+def check_contract(c: Contract) -> List[Function]:
+  results_raw: List[Function] = []
+
+  if len(swap_functions) != len(swap_route_arg_pos):
+    print("ERROR - Array lengths not matching")
+    return results_raw
+  # skip test contracts
+  if any( x in c.name for x in ["Test", "Mock"]) or any(x in c.name.lower() for x in banned_contracts_partial): 
+    return results_raw
+
+  # to filter constructors for old solidity versions
+  inherited_contracts = get_inherited_contracts(c) + [c.name] 
+
+  # filter unwanted funcs (also checked later recursively for nested calls)
+  to_inspect = (x for x in c.functions if (
+    # filter banned functions and old solc constructors
+    x.name not in (banned_funcs + inherited_contracts) and 
+    not any(y in x.name for y in banned_funcs_partial) and
+    not x.pure and not x.view and
+    x.visibility in ["public", "external"] and # internal functions inspected through internal calls to keep the flow consistent
+    x.is_implemented))
+
+  for f in to_inspect: 
+    verb = False
+    if f.name == "-":
+      verb = True
+    ctx = Context(c, f, f, [True for i in range(len(f.parameters))], verb)
+    check_function(f.entry_point, ctx)
+    if len(ctx.hits):
+      results_raw += ctx.hits
+  return results_raw
+
+
+def check_function(node: Optional[Node], ctx: Context):
+  if node is None:
+    return False
+  
+  if ctx.function.name in banned_funcs or any(x in ctx.function.name for x in banned_funcs_partial):
+    return False
+
+  if is_modifier_protected(ctx.function): # TODO enhance 
+    return False
+
+  if node in ctx.visited:
+    return False
+  ctx.visited.append(node)
+
+  # debug
+  if ctx.verb:
+    print(str(node))
+    for ir in node.irs:
+      print("    " + str(ir) + "    " + str(type(ir)))
+
+  # check if the input parameters are checked, and remove taint flag if so
+  if node.contains_if() or node.contains_require_or_assert() and "address(0)" not in str(node):
+    for i in range(len(ctx.function.parameters)):
+      param = ctx.function.parameters[i]
+      if isinstance(param, LocalVariable) and not isinstance(param.type, ArrayType): # only look for checks on single addresses, not on path (which most likely will be length)
+        if param in node.local_variables_read:
+          ctx.args_tainted_mask[i] = False
+          ctx.entrypoint_params_index_dependency[i] = False
+
+
+  for ir in node.irs:
+    # check for external calls 
+    if isinstance(ir, HighLevelCall):
+      for i in range(len(swap_functions)): # check if 
+        if hasattr(ir.function, "name") and ir.function.name == swap_functions[i] and len(ir.arguments) >= swap_route_arg_pos[i] + 1:
+          path_argument = ir.arguments[swap_route_arg_pos[i]]
+          tainted_indexes = is_dependent_on_any_tainted(path_argument, ctx.function.parameters, ctx.args_tainted_mask, ctx.function)
+          if len(tainted_indexes):
+            if not (ctx.function.name == ctx.entry_point.name and ctx.function.name in swap_functions):
+              _ctx = ctx.make_copy()
+              # list entry parameters used to compute the route 
+              entry_params_used = []
+              for ti in tainted_indexes: # indici dei parametri della funzione corrente, da cui dipende la path
+                for pi in ctx.entrypoint_params_index_dependency[ti]: # indici dei parametri dell'entrypoint 
+                  entry_params_used.append(ctx.entry_point.parameters[pi].name)
+              ctx.hits.append(Hit(_ctx.entry_point, _ctx.function, path_argument.name, _ctx.call_chain, entry_params_used, swap_functions[i]))
+
+    # internal call to inspect
+    elif isinstance(ir, InternalCall):
+      # prepare new context for the callee
+      ctx_callee = ctx.make_copy()
+      ctx_callee.call_chain.append(ir.function.name)
+      # map tainted bool mask from caller parameters to callee arguments
+      taint_mask = []
+      ctx_callee.entrypoint_params_index_dependency = [[] for i in range(len(ir.arguments))] # empty out to fill in the coming loop
+      for i in range(len(ir.arguments)):
+        carg = ir.arguments[i]
+        tainted_indexes = is_dependent_on_any_tainted(carg, ctx.function.parameters, ctx.args_tainted_mask, ctx.function)
+        taint_mask.append(True if len(tainted_indexes) else False)
+        for ti in tainted_indexes:
+          for epi in ctx.entrypoint_params_index_dependency[ti]:
+            ctx_callee.entrypoint_params_index_dependency[i].append(epi)
+
+      ctx_callee.args_tainted_mask = taint_mask
+      ctx_callee.function = ir.function
+      check_function(ir.function.entry_point, ctx_callee)
+      if len(ctx_callee.hits) > len(ctx.hits): # callee has new hits
+        for i in range(len(ctx_callee.hits), len(ctx.hits)):
+          ctx.hits.append(ctx_callee.hits[i])
+
+  # sons inspection
+  ret = False
+  for son in node.sons:
+      ret = ret or check_function(son, ctx) # ctx by reference to get it populated with flags
+  return ret
+
+
+def is_dependent_on_any_tainted(checked_var: LocalVariable, vars_list: List[LocalVariable], tainted_mask: List[bool], context) -> List[int]:
+  ret: List[int] = []
+  if not type(checked_var) is list: # can be list eg foo([bar, 0], par)
+    checked_var = [checked_var]
+  for i in range(len(checked_var)):
+    if not isinstance(checked_var[i], LocalVariable):
+      continue
+    if not len(vars_list) == len(tainted_mask):
+      print("ERROR: Mismatch array length vars_list vs tainted_mask")
+      return []
+    for j in range(len(vars_list)):
+      if not tainted_mask[j]: 
+        continue
+      if is_dependent(checked_var[i], vars_list[j], context):
+        ret.append(j)
+  return ret
+
+
+def get_inherited_contracts(contract: Contract) -> List[str]:
+    return list(x.name for x in contract.inheritance)
 
+def is_modifier_protected(func: Function) -> bool:
+  bannedPattern = ['admin', 'owner', 'role', 'only', 'permission', 'initializ', 'auth']
+  for mod in func.modifiers:
+    if any(x in mod.name.lower() for x in bannedPattern):
+      return True
+  return False
 
 class UniswapV2(AbstractDetector):
     """
@@ -125,11 +313,10 @@ def _maxReturn_max(self, fun: Function) -> bool:
                             return True
         return False
 
-    #TODO детектить сет адресов в важных функциях через параметры, детектить в сторадж переменных
     def _has_bad_token(self, fun: Function) -> bool:
         """Checks if deflationary or rebase tokens are used"""
         absolute_path = os.path.dirname(__file__)
-        relative_path = "../../utils/deflat_tokens.json"
+        relative_path = "../utils/deflat_tokens.json"
         full_path = os.path.join(absolute_path, relative_path)
         fileJson = open(full_path)
         data = json.load(fileJson)
@@ -145,8 +332,28 @@ def _has_bad_token(self, fun: Function) -> bool:
     def _detect(self) -> List[Output]:
         """Main function"""
         res = []
+        results_raw: List[Hit] = []
+        results: List[Output] = []
         if "pess-uni-v2" in sys.argv:   # launch only if detector in terminal is present
             for contract in self.compilation_unit.contracts_derived:
+                results_raw += check_contract(contract)
+                for f in results_raw:
+                    info = [
+                    f"Tainted route '",
+                    f.param_name,
+                    "' for function '",
+                    f.swap_func,
+                    "'\n in function '",
+                    f.hit_function,
+                    "'\n from entry point '",
+                    f.entry_point,
+                    "'\n Call chain (one of the possible ones): ",
+                    str(f.call_chain),
+                    "\n Entrypoint params used: ",
+                    str(f.entry_params_used),
+                    "\n\n"
+                    ]
+                    res.append(self.generate_result(info))
                 pair_used = self._pair_used(contract)
                 for f in contract.functions:
                     pair_balance_used = self._pair_balance_used(f)
diff --git a/slither_pess/detectors/unprotected_initialize.py b/slither_pess/detectors/unprotected_initialize.py
index 005a069..2be2264 100644
--- a/slither_pess/detectors/unprotected_initialize.py
+++ b/slither_pess/detectors/unprotected_initialize.py
@@ -9,19 +9,18 @@ class UnprotectedInitialize(AbstractDetector):
     Sees if a contract has initialize functions that are not protected by anything.
     """
 
-    ARGUMENT = 'pess-unprotected-initialize' # slither will launch the detector with slither.py --detect mydetector
-    HELP = 'The contract must have its initialize function protected'
+    ARGUMENT = "pess-unprotected-initialize"  # slither will launch the detector with slither.py --detect mydetector
+    HELP = "The contract must have its initialize function protected"
     IMPACT = DetectorClassification.HIGH
     CONFIDENCE = DetectorClassification.LOW
 
-    WIKI = 'https://github.com/pessimistic-io/slitherin/blob/master/docs/unprotected_initialize.md'
-    WIKI_TITLE = 'Unprotected Initialize'
+    WIKI = "https://github.com/pessimistic-io/slitherin/blob/master/docs/unprotected_initialize.md"
+    WIKI_TITLE = "Unprotected Initialize"
     WIKI_DESCRIPTION = "Initializers must be protected"
-    WIKI_EXPLOIT_SCENARIO = '-'
-    WIKI_RECOMMENDATION = 'Protect initializers with modifiers/require statements'
+    WIKI_EXPLOIT_SCENARIO = "-"
+    WIKI_RECOMMENDATION = "Protect initializers with modifiers/require statements"
 
-
-    def _is_initialize(self, fun: Function) -> bool: 
+    def _is_initialize(self, fun: Function) -> bool:
         """Checks if function is initialize one"""
         if isinstance(fun, Function) and "init" in fun.name:
             return True
@@ -43,19 +42,26 @@ def _has_require(self, fun: Function) -> bool:
                         return True
         return False
 
-
     def _detect(self) -> List[Output]:
         """Main function"""
         res = []
         for contract in self.compilation_unit.contracts_derived:
+            if contract.is_interface:
+                continue
             for f in contract.functions_and_modifiers_declared:
                 x = self._is_initialize(f)
                 if x:
                     is_safe = self._has_modifiers(f)
                     is_safe2 = self._has_require(f)
                     if not is_safe and not is_safe2:
-                        res.append(self.generate_result([
-                            "Function ",
-                            f, ' is an unprotected initializer.',
-                            '\n']))
+                        res.append(
+                            self.generate_result(
+                                [
+                                    "Function ",
+                                    f,
+                                    " is an unprotected initializer.",
+                                    "\n",
+                                ]
+                            )
+                        )
         return res
diff --git a/slither_pess/detectors/unprotected_setter.py b/slither_pess/detectors/unprotected_setter.py
index bfddb39..d0d5e5f 100644
--- a/slither_pess/detectors/unprotected_setter.py
+++ b/slither_pess/detectors/unprotected_setter.py
@@ -8,52 +8,63 @@ class UnprotectedSetter(AbstractDetector):
     Sees if contract contains a setter, that changes contract paramater without modifier protection or access control inside the function
     """
 
-    ARGUMENT = 'pess-unprotected-setter' # slither will launch the detector with slither.py --detect mydetector
-    HELP = 'Contract critical storage parameters might be changed by anyone'
+    ARGUMENT = "pess-unprotected-setter"  # slither will launch the detector with slither.py --detect mydetector
+    HELP = "Contract critical storage parameters might be changed by anyone"
     IMPACT = DetectorClassification.HIGH
     CONFIDENCE = DetectorClassification.MEDIUM
 
-    WIKI = 'https://github.com/pessimistic-io/slitherin/blob/master/docs/unprotected_setter.md'
-    WIKI_TITLE = 'Unprotected Setter'
+    WIKI = "https://github.com/pessimistic-io/slitherin/blob/master/docs/unprotected_setter.md"
+    WIKI_TITLE = "Unprotected Setter"
     WIKI_DESCRIPTION = "Usually all setters must be protected with access control"
-    WIKI_EXPLOIT_SCENARIO = '-'
-    WIKI_RECOMMENDATION = 'Add access control'
-
+    WIKI_EXPLOIT_SCENARIO = "-"
+    WIKI_RECOMMENDATION = "Add access control"
 
     def is_setter(self, fun, params=None):
         if not params:
             params = fun.parameters
         for n in fun.nodes:
-            if(n.type==NodeType.EXPRESSION):
+            if n.type == NodeType.EXPRESSION:
                 for v in n.state_variables_written:
-                    lr = str(n.expression).split(' = ')
-                    if len(lr)>1:
+                    lr = str(n.expression).split(" = ")
+                    if len(lr) > 1:
                         left = lr[0]
                         right = lr[1]
                         for p in params:
-                            if '.' in left: continue
-                            if '[' in left: continue
-                            if right==str(p): return left
+                            if "." in left:
+                                continue
+                            if "[" in left:
+                                continue
+                            if right == str(p):
+                                return left
         return None
 
     def has_access_control(self, fun):
         for m in fun.modifiers:
-            for m.name in ['initializer', 'onlyOwner']:
+            for m.name in ["initializer", "onlyOwner"]:
                 return True
-        if fun.visibility in ['internal','private']:
+        if fun.visibility in ["internal", "private"]:
             return True
         return fun.is_protected()
 
     def _detect(self):
         res = []
         for contract in self.compilation_unit.contracts_derived:
+            if contract.is_interface:
+                continue
             for f in contract.functions:
                 if not self.has_access_control(f):
                     x = self.is_setter(f)
-                    if (x!= None):
-                        res.append(self.generate_result([
-                            "Function", ' ',
-                            f, ' is a non-protected setter ',
-                            x, ' is written'
-                            '\n']))
+                    if x != None:
+                        res.append(
+                            self.generate_result(
+                                [
+                                    "Function",
+                                    " ",
+                                    f,
+                                    " is a non-protected setter ",
+                                    x,
+                                    " is written" "\n",
+                                ]
+                            )
+                        )
         return res
diff --git a/utils/deflat_tokens.json b/slither_pess/utils/deflat_tokens.json
similarity index 100%
rename from utils/deflat_tokens.json
rename to slither_pess/utils/deflat_tokens.json
diff --git a/utils/rebase_tokens.json b/slither_pess/utils/rebase_tokens.json
similarity index 100%
rename from utils/rebase_tokens.json
rename to slither_pess/utils/rebase_tokens.json


Test patch:
diff --git a/tests/double_entry_token.sol b/tests/double_entry_token.sol
new file mode 100644
index 0000000..53d9884
--- /dev/null
+++ b/tests/double_entry_token.sol
@@ -0,0 +1,39 @@
+// SPDX-License-Identifier: SEE LICENSE IN LICENSE
+pragma solidity ^0.8.0;
+
+import "../node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol";
+
+contract DoubleEntryTokenTest_vuln {
+    function vulnerable(IERC20[] calldata tokens0, address[] calldata tokens1) external {
+        for (uint256 i = 0; i < tokens0.length; i++){
+            uint256 bal = tokens0[i].balanceOf(address(this));
+            tokens0[i].transfer(tokens1[i], bal);
+        }
+    }
+
+    function not_vulnerable(address[] calldata users) view external returns(uint256) {
+        uint256 total = 0;
+        for (uint256 i = 0; i < users.length; i++){
+            total += payable(users[i]).balance;
+        }
+        return total;
+    }
+
+    /**
+     * @dev Extracted from the Openzeppelin Governor contract as an example 
+     * https://github.com/OpenZeppelin/openzeppelin-contracts/blob/f347b410cf6aeeaaf5197e1fece139c793c03b2b/contracts/governance/Governor.sol#L414)
+     */
+    function _afterExecute(
+        uint256 /* proposalId */,
+        address[] memory /* targets */,
+        uint256[] memory /* values */,
+        bytes[] memory /* calldatas */,
+        bytes32 /*descriptionHash*/
+    ) internal virtual {
+        // if (_executor() != address(this)) {
+        //     if (!_governanceCall.empty()) {
+        //         _governanceCall.clear();
+        //     }
+        // }
+    }
+}
\ No newline at end of file
diff --git a/tests/dubious_typecast_test.sol b/tests/dubious_typecast_test.sol
index 00b6fd4..2bdaa21 100644
--- a/tests/dubious_typecast_test.sol
+++ b/tests/dubious_typecast_test.sol
@@ -1,13 +1,26 @@
 pragma solidity ^0.8.0;
 
 contract dubious_typecast_test {
-
-    function getOne () public pure returns (bytes32){
+    function getOne() public pure returns (bytes32) {
         return bytes32(bytes1(0x01));
     } // actully returns "bytes32: 0x0100000000000000000000000000000000000000000000000000000000000000"
 
-
-    function number_not_clear () external pure returns (uint8){
+    function number_not_clear() external pure returns (uint8) {
+        uint t = 256;
+        uint8 k = uint8(t); //new:this is dubious
         return uint8(uint256(1e18));
     } // actually returns 0
+
+    function _approve(
+        address owner,
+        address spender,
+        uint256 amount
+    ) internal virtual {}
+
+    function address_castNotvulnerable() external returns (address) {
+        dubious_typecast_test d;
+        _approve(address(this), address(d), 0); //new:this is FP
+
+        return address(d);
+    } // actually returns 0
 }
diff --git a/tests/for_continue_increment.sol b/tests/for_continue_increment.sol
index 7854cec..8b1f431 100644
--- a/tests/for_continue_increment.sol
+++ b/tests/for_continue_increment.sol
@@ -1,4 +1,4 @@
-pragma solidity 0.8.18;
+pragma solidity ^0.8.18;
 
 contract Target{
 
diff --git a/tests/nft_approve_warning_test.sol b/tests/nft_approve_warning_test.sol
index e426aa8..a53f7b0 100644
--- a/tests/nft_approve_warning_test.sol
+++ b/tests/nft_approve_warning_test.sol
@@ -20,4 +20,19 @@ contract nft_approve_warning_test {
         nft.transferFrom(msg.sender, to, tokenId);
     }
 
-}
\ No newline at end of file
+}
+
+pragma solidity ^0.8.19;
+
+interface IERC20 {
+    function transferFrom(address from, address to, uint256 amount) external returns (bool);
+}
+
+contract Test
+{
+    IERC20 immutable TOKEN = IERC20(address(0));
+    function test() internal {
+        TOKEN.transferFrom(address(this), address(0), 0);
+    }
+}
+
diff --git a/tests/strange_setter_test.sol b/tests/strange_setter_test.sol
index 8dbe588..b50e80a 100644
--- a/tests/strange_setter_test.sol
+++ b/tests/strange_setter_test.sol
@@ -19,6 +19,11 @@ contract StrangeSetter {
         a = setter;
     }
 
+    function set_vulnerable_mapping(uint256 _toSet) external onlyOwner {
+        uint256 vars = _toSet;
+        toSet = vars;
+    }
+
     function setBuilder(bytes32 nameHash, address builder) public onlyOwner{
         s_builders[nameHash] = builder;
     }
@@ -46,3 +51,7 @@ contract StrangeConstructor {
     }
 }
 
+contract OkConstructor {    //if constructor has no parameters or is empty - do not detect
+    constructor(){}
+}
+
diff --git a/tests/unprotected_initialize_test.sol b/tests/unprotected_initialize_test.sol
index c712c41..edb753f 100644
--- a/tests/unprotected_initialize_test.sol
+++ b/tests/unprotected_initialize_test.sol
@@ -1,5 +1,9 @@
 pragma solidity ^0.8.0;
 
+interface I {
+    function initialize() external;
+}
+
 contract unprotected_initialize {
     uint256 toSet;
     bool isProtected = true;
@@ -10,33 +14,33 @@ contract unprotected_initialize {
         _;
     }
 
-    function initialize_ok1 (uint256 setter) external onlyOwner {
+    function initialize_ok1(uint256 setter) external onlyOwner {
         uint256 a = 10;
         toSet = setter + a;
     }
 
-    function initialize_ok2 (uint256 setter) external {
+    function initialize_ok2(uint256 setter) external {
         require(msg.sender == owner);
         uint256 a = 10;
         toSet = setter + a;
     }
 
-    function initialize_vuln (uint256 setter) external {
+    function initialize_vuln(uint256 setter) external {
         toSet = setter;
     }
 
-    function init_ok1 (uint256 setter) external onlyOwner {
+    function init_ok1(uint256 setter) external onlyOwner {
         uint256 a = 10;
         toSet = setter + a;
     }
 
-    function init_ok2 (uint256 setter) external {
+    function init_ok2(uint256 setter) external {
         require(msg.sender == owner);
         uint256 a = 10;
         toSet = setter + a;
     }
 
-    function init_vuln (uint256 setter) external {
+    function init_vuln(uint256 setter) external {
         toSet = setter;
     }
 }