We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[Bug] contract reports ether as locked when ether is sent in Yul
The following contract reports ether as locked despite it being sent in a Yul block
```
contract FPLockedEther {
  receive() payable external {}

  function yulSendEther() external {
    bool success;
    assembly {
      success := call(gas(), caller(), balance(address()), 0,0,0,0)
    }
  }
}
```
```
Contract locking ether found:
	Contract FPLockedEther (locked-ether.sol#1-13) has payable functions:
	 - FPLockedEther.receive() (locked-ether.sol#2-3)
	But does not have a function to withdraw the ether
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#contracts-that-lock-ether
```

It could be that the IR is incorrect here as it should not be a `SOLIDITY_CALL`
```
Contract FPLockedEther
	Function FPLockedEther.receive() (*)
	Function FPLockedEther.yulSendEther() (*)
		Expression: success = call(uint256,uint256,uint256,uint256,uint256,uint256,uint256)(gas()(),caller()(),balance(uint256)(address()()),0,0,0,0)
		IRs:
			TMP_0(uint256) = SOLIDITY_CALL gas()()
			TMP_1(address) := msg.sender(address)
			TMP_2 = CONVERT this to address
			TMP_3(uint256) = SOLIDITY_CALL balance(uint256)(TMP_2)
			TMP_4(uint256) = SOLIDITY_CALL call(uint256,uint256,uint256,uint256,uint256,uint256,uint256)(TMP_0,TMP_1,TMP_3,0,0,0,0)
			success(bool) := TMP_4(uint256)
```

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `slither/detectors/attributes/locked_ether.py`
Content:
```
1 """
2     Check if ethers are locked in the contract
3 """
4 from typing import List
5 
6 from slither.core.declarations.contract import Contract
7 from slither.detectors.abstract_detector import (
8     AbstractDetector,
9     DetectorClassification,
10     DETECTOR_INFO,
11 )
12 from slither.slithir.operations import (
13     HighLevelCall,
14     LowLevelCall,
15     Send,
16     Transfer,
17     NewContract,
18     LibraryCall,
19     InternalCall,
20 )
21 from slither.utils.output import Output
22 
23 
24 class LockedEther(AbstractDetector):  # pylint: disable=too-many-nested-blocks
25 
26     ARGUMENT = "locked-ether"
27     HELP = "Contracts that lock ether"
28     IMPACT = DetectorClassification.MEDIUM
29     CONFIDENCE = DetectorClassification.HIGH
30 
31     WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#contracts-that-lock-ether"
32 
33     WIKI_TITLE = "Contracts that lock Ether"
34     WIKI_DESCRIPTION = "Contract with a `payable` function, but without a withdrawal capacity."
35 
36     # region wiki_exploit_scenario
37     WIKI_EXPLOIT_SCENARIO = """
38 ```solidity
39 pragma solidity 0.4.24;
40 contract Locked{
41     function receive() payable public{
42     }
43 }
44 ```
45 Every Ether sent to `Locked` will be lost."""
46     # endregion wiki_exploit_scenario
47 
48     WIKI_RECOMMENDATION = "Remove the payable attribute or add a withdraw function."
49 
50     @staticmethod
51     def do_no_send_ether(contract: Contract) -> bool:
52         functions = contract.all_functions_called
53         to_explore = functions
54         explored = []
55         while to_explore:  # pylint: disable=too-many-nested-blocks
56             functions = to_explore
57             explored += to_explore
58             to_explore = []
59             for function in functions:
60                 calls = [c.name for c in function.internal_calls]
61                 if "suicide(address)" in calls or "selfdestruct(address)" in calls:
62                     return False
63                 for node in function.nodes:
64                     for ir in node.irs:
65                         if isinstance(
66                             ir,
67                             (Send, Transfer, HighLevelCall, LowLevelCall, NewContract),
68                         ):
69                             if ir.call_value and ir.call_value != 0:
70                                 return False
71                         if isinstance(ir, (LowLevelCall)):
72                             if ir.function_name in ["delegatecall", "callcode"]:
73                                 return False
74                         # If a new internal call or librarycall
75                         # Add it to the list to explore
76                         # InternalCall if to follow internal call in libraries
77                         if isinstance(ir, (InternalCall, LibraryCall)):
78                             if not ir.function in explored:
79                                 to_explore.append(ir.function)
80 
81         return True
82 
83     def _detect(self) -> List[Output]:
84         results = []
85 
86         for contract in self.compilation_unit.contracts_derived:
87             if contract.is_signature_only():
88                 continue
89             funcs_payable = [function for function in contract.functions if function.payable]
90             if funcs_payable:
91                 if self.do_no_send_ether(contract):
92                     info: DETECTOR_INFO = ["Contract locking ether found:\n"]
93                     info += ["\tContract ", contract, " has payable functions:\n"]
94                     for function in funcs_payable:
95                         info += ["\t - ", function, "\n"]
96                     info += "\tBut does not have a function to withdraw the ether\n"
97 
98                     json = self.generate_result(info)
99 
100                     results.append(json)
101 
102         return results
103
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/slither/detectors/attributes/locked_ether.py b/slither/detectors/attributes/locked_ether.py
--- a/slither/detectors/attributes/locked_ether.py
+++ b/slither/detectors/attributes/locked_ether.py
@@ -3,7 +3,7 @@
 """
 from typing import List
 
-from slither.core.declarations.contract import Contract
+from slither.core.declarations import Contract, SolidityFunction
 from slither.detectors.abstract_detector import (
     AbstractDetector,
     DetectorClassification,
@@ -17,7 +17,9 @@
     NewContract,
     LibraryCall,
     InternalCall,
+    SolidityCall,
 )
+from slither.slithir.variables import Constant
 from slither.utils.output import Output
 
 
@@ -68,8 +70,28 @@
                         ):
                             if ir.call_value and ir.call_value != 0:
                                 return False
-                        if isinstance(ir, (LowLevelCall)):
-                            if ir.function_name in ["delegatecall", "callcode"]:
+                        if isinstance(ir, (LowLevelCall)) and ir.function_name in [
+                            "delegatecall",
+                            "callcode",
+                        ]:
+                            return False
+                        if isinstance(ir, SolidityCall):
+                            call_can_send_ether = ir.function in [
+                                SolidityFunction(
+                                    "delegatecall(uint256,uint256,uint256,uint256,uint256,uint256)"
+                                ),
+                                SolidityFunction(
+                                    "callcode(uint256,uint256,uint256,uint256,uint256,uint256,uint256)"
+                                ),
+                                SolidityFunction(
+                                    "call(uint256,uint256,uint256,uint256,uint256,uint256,uint256)"
+                                ),
+                            ]
+                            nonzero_call_value = call_can_send_ether and (
+                                not isinstance(ir.arguments[2], Constant)
+                                or ir.arguments[2].value != 0
+                            )
+                            if nonzero_call_value:
                                 return False
                         # If a new internal call or librarycall
                         # Add it to the list to explore

{"golden_diff": "diff --git a/slither/detectors/attributes/locked_ether.py b/slither/detectors/attributes/locked_ether.py\n--- a/slither/detectors/attributes/locked_ether.py\n+++ b/slither/detectors/attributes/locked_ether.py\n@@ -3,7 +3,7 @@\n \"\"\"\n from typing import List\n \n-from slither.core.declarations.contract import Contract\n+from slither.core.declarations import Contract, SolidityFunction\n from slither.detectors.abstract_detector import (\n     AbstractDetector,\n     DetectorClassification,\n@@ -17,7 +17,9 @@\n     NewContract,\n     LibraryCall,\n     InternalCall,\n+    SolidityCall,\n )\n+from slither.slithir.variables import Constant\n from slither.utils.output import Output\n \n \n@@ -68,8 +70,28 @@\n                         ):\n                             if ir.call_value and ir.call_value != 0:\n                                 return False\n-                        if isinstance(ir, (LowLevelCall)):\n-                            if ir.function_name in [\"delegatecall\", \"callcode\"]:\n+                        if isinstance(ir, (LowLevelCall)) and ir.function_name in [\n+                            \"delegatecall\",\n+                            \"callcode\",\n+                        ]:\n+                            return False\n+                        if isinstance(ir, SolidityCall):\n+                            call_can_send_ether = ir.function in [\n+                                SolidityFunction(\n+                                    \"delegatecall(uint256,uint256,uint256,uint256,uint256,uint256)\"\n+                                ),\n+                                SolidityFunction(\n+                                    \"callcode(uint256,uint256,uint256,uint256,uint256,uint256,uint256)\"\n+                                ),\n+                                SolidityFunction(\n+                                    \"call(uint256,uint256,uint256,uint256,uint256,uint256,uint256)\"\n+                                ),\n+                            ]\n+                            nonzero_call_value = call_can_send_ether and (\n+                                not isinstance(ir.arguments[2], Constant)\n+                                or ir.arguments[2].value != 0\n+                            )\n+                            if nonzero_call_value:\n                                 return False\n                         # If a new internal call or librarycall\n                         # Add it to the list to explore\n", "issue": "[Bug] contract reports ether as locked when ether is sent in Yul\nThe following contract reports ether as locked despite it being sent in a Yul block\r\n```\r\ncontract FPLockedEther {\r\n  receive() payable external {}\r\n\r\n  function yulSendEther() external {\r\n    bool success;\r\n    assembly {\r\n      success := call(gas(), caller(), balance(address()), 0,0,0,0)\r\n    }\r\n  }\r\n}\r\n```\r\n```\r\nContract locking ether found:\r\n\tContract FPLockedEther (locked-ether.sol#1-13) has payable functions:\r\n\t - FPLockedEther.receive() (locked-ether.sol#2-3)\r\n\tBut does not have a function to withdraw the ether\r\nReference: https://github.com/crytic/slither/wiki/Detector-Documentation#contracts-that-lock-ether\r\n```\r\n\r\nIt could be that the IR is incorrect here as it should not be a `SOLIDITY_CALL`\r\n```\r\nContract FPLockedEther\r\n\tFunction FPLockedEther.receive() (*)\r\n\tFunction FPLockedEther.yulSendEther() (*)\r\n\t\tExpression: success = call(uint256,uint256,uint256,uint256,uint256,uint256,uint256)(gas()(),caller()(),balance(uint256)(address()()),0,0,0,0)\r\n\t\tIRs:\r\n\t\t\tTMP_0(uint256) = SOLIDITY_CALL gas()()\r\n\t\t\tTMP_1(address) := msg.sender(address)\r\n\t\t\tTMP_2 = CONVERT this to address\r\n\t\t\tTMP_3(uint256) = SOLIDITY_CALL balance(uint256)(TMP_2)\r\n\t\t\tTMP_4(uint256) = SOLIDITY_CALL call(uint256,uint256,uint256,uint256,uint256,uint256,uint256)(TMP_0,TMP_1,TMP_3,0,0,0,0)\r\n\t\t\tsuccess(bool) := TMP_4(uint256)\r\n```\n", "before_files": [{"content": "\"\"\"\n    Check if ethers are locked in the contract\n\"\"\"\nfrom typing import List\n\nfrom slither.core.declarations.contract import Contract\nfrom slither.detectors.abstract_detector import (\n    AbstractDetector,\n    DetectorClassification,\n    DETECTOR_INFO,\n)\nfrom slither.slithir.operations import (\n    HighLevelCall,\n    LowLevelCall,\n    Send,\n    Transfer,\n    NewContract,\n    LibraryCall,\n    InternalCall,\n)\nfrom slither.utils.output import Output\n\n\nclass LockedEther(AbstractDetector):  # pylint: disable=too-many-nested-blocks\n\n    ARGUMENT = \"locked-ether\"\n    HELP = \"Contracts that lock ether\"\n    IMPACT = DetectorClassification.MEDIUM\n    CONFIDENCE = DetectorClassification.HIGH\n\n    WIKI = \"https://github.com/crytic/slither/wiki/Detector-Documentation#contracts-that-lock-ether\"\n\n    WIKI_TITLE = \"Contracts that lock Ether\"\n    WIKI_DESCRIPTION = \"Contract with a `payable` function, but without a withdrawal capacity.\"\n\n    # region wiki_exploit_scenario\n    WIKI_EXPLOIT_SCENARIO = \"\"\"\n```solidity\npragma solidity 0.4.24;\ncontract Locked{\n    function receive() payable public{\n    }\n}\n```\nEvery Ether sent to `Locked` will be lost.\"\"\"\n    # endregion wiki_exploit_scenario\n\n    WIKI_RECOMMENDATION = \"Remove the payable attribute or add a withdraw function.\"\n\n    @staticmethod\n    def do_no_send_ether(contract: Contract) -> bool:\n        functions = contract.all_functions_called\n        to_explore = functions\n        explored = []\n        while to_explore:  # pylint: disable=too-many-nested-blocks\n            functions = to_explore\n            explored += to_explore\n            to_explore = []\n            for function in functions:\n                calls = [c.name for c in function.internal_calls]\n                if \"suicide(address)\" in calls or \"selfdestruct(address)\" in calls:\n                    return False\n                for node in function.nodes:\n                    for ir in node.irs:\n                        if isinstance(\n                            ir,\n                            (Send, Transfer, HighLevelCall, LowLevelCall, NewContract),\n                        ):\n                            if ir.call_value and ir.call_value != 0:\n                                return False\n                        if isinstance(ir, (LowLevelCall)):\n                            if ir.function_name in [\"delegatecall\", \"callcode\"]:\n                                return False\n                        # If a new internal call or librarycall\n                        # Add it to the list to explore\n                        # InternalCall if to follow internal call in libraries\n                        if isinstance(ir, (InternalCall, LibraryCall)):\n                            if not ir.function in explored:\n                                to_explore.append(ir.function)\n\n        return True\n\n    def _detect(self) -> List[Output]:\n        results = []\n\n        for contract in self.compilation_unit.contracts_derived:\n            if contract.is_signature_only():\n                continue\n            funcs_payable = [function for function in contract.functions if function.payable]\n            if funcs_payable:\n                if self.do_no_send_ether(contract):\n                    info: DETECTOR_INFO = [\"Contract locking ether found:\\n\"]\n                    info += [\"\\tContract \", contract, \" has payable functions:\\n\"]\n                    for function in funcs_payable:\n                        info += [\"\\t - \", function, \"\\n\"]\n                    info += \"\\tBut does not have a function to withdraw the ether\\n\"\n\n                    json = self.generate_result(info)\n\n                    results.append(json)\n\n        return results\n", "path": "slither/detectors/attributes/locked_ether.py"}], "after_files": [{"content": "\"\"\"\n    Check if ethers are locked in the contract\n\"\"\"\nfrom typing import List\n\nfrom slither.core.declarations import Contract, SolidityFunction\nfrom slither.detectors.abstract_detector import (\n    AbstractDetector,\n    DetectorClassification,\n    DETECTOR_INFO,\n)\nfrom slither.slithir.operations import (\n    HighLevelCall,\n    LowLevelCall,\n    Send,\n    Transfer,\n    NewContract,\n    LibraryCall,\n    InternalCall,\n    SolidityCall,\n)\nfrom slither.slithir.variables import Constant\nfrom slither.utils.output import Output\n\n\nclass LockedEther(AbstractDetector):  # pylint: disable=too-many-nested-blocks\n\n    ARGUMENT = \"locked-ether\"\n    HELP = \"Contracts that lock ether\"\n    IMPACT = DetectorClassification.MEDIUM\n    CONFIDENCE = DetectorClassification.HIGH\n\n    WIKI = \"https://github.com/crytic/slither/wiki/Detector-Documentation#contracts-that-lock-ether\"\n\n    WIKI_TITLE = \"Contracts that lock Ether\"\n    WIKI_DESCRIPTION = \"Contract with a `payable` function, but without a withdrawal capacity.\"\n\n    # region wiki_exploit_scenario\n    WIKI_EXPLOIT_SCENARIO = \"\"\"\n```solidity\npragma solidity 0.4.24;\ncontract Locked{\n    function receive() payable public{\n    }\n}\n```\nEvery Ether sent to `Locked` will be lost.\"\"\"\n    # endregion wiki_exploit_scenario\n\n    WIKI_RECOMMENDATION = \"Remove the payable attribute or add a withdraw function.\"\n\n    @staticmethod\n    def do_no_send_ether(contract: Contract) -> bool:\n        functions = contract.all_functions_called\n        to_explore = functions\n        explored = []\n        while to_explore:  # pylint: disable=too-many-nested-blocks\n            functions = to_explore\n            explored += to_explore\n            to_explore = []\n            for function in functions:\n                calls = [c.name for c in function.internal_calls]\n                if \"suicide(address)\" in calls or \"selfdestruct(address)\" in calls:\n                    return False\n                for node in function.nodes:\n                    for ir in node.irs:\n                        if isinstance(\n                            ir,\n                            (Send, Transfer, HighLevelCall, LowLevelCall, NewContract),\n                        ):\n                            if ir.call_value and ir.call_value != 0:\n                                return False\n                        if isinstance(ir, (LowLevelCall)) and ir.function_name in [\n                            \"delegatecall\",\n                            \"callcode\",\n                        ]:\n                            return False\n                        if isinstance(ir, SolidityCall):\n                            call_can_send_ether = ir.function in [\n                                SolidityFunction(\n                                    \"delegatecall(uint256,uint256,uint256,uint256,uint256,uint256)\"\n                                ),\n                                SolidityFunction(\n                                    \"callcode(uint256,uint256,uint256,uint256,uint256,uint256,uint256)\"\n                                ),\n                                SolidityFunction(\n                                    \"call(uint256,uint256,uint256,uint256,uint256,uint256,uint256)\"\n                                ),\n                            ]\n                            nonzero_call_value = call_can_send_ether and (\n                                not isinstance(ir.arguments[2], Constant)\n                                or ir.arguments[2].value != 0\n                            )\n                            if nonzero_call_value:\n                                return False\n                        # If a new internal call or librarycall\n                        # Add it to the list to explore\n                        # InternalCall if to follow internal call in libraries\n                        if isinstance(ir, (InternalCall, LibraryCall)):\n                            if not ir.function in explored:\n                                to_explore.append(ir.function)\n\n        return True\n\n    def _detect(self) -> List[Output]:\n        results = []\n\n        for contract in self.compilation_unit.contracts_derived:\n            if contract.is_signature_only():\n                continue\n            funcs_payable = [function for function in contract.functions if function.payable]\n            if funcs_payable:\n                if self.do_no_send_ether(contract):\n                    info: DETECTOR_INFO = [\"Contract locking ether found:\\n\"]\n                    info += [\"\\tContract \", contract, \" has payable functions:\\n\"]\n                    for function in funcs_payable:\n                        info += [\"\\t - \", function, \"\\n\"]\n                    info += \"\\tBut does not have a function to withdraw the ether\\n\"\n\n                    json = self.generate_result(info)\n\n                    results.append(json)\n\n        return results\n", "path": "slither/detectors/attributes/locked_ether.py"}]}