Repository: crytic/slither

Issue:
[False-Positive]: Erroneous "should be constant" detector
### Describe the false alarm that Slither raise and how you know it's inaccurate:

Similar reproduction steps as https://github.com/crytic/slither/issues/2324. This time, you'll see a `L1Block.blobBaseFee (src/L2/L1Block.sol#50) should be constant` finding. 

However, that variable is set using assembly: `sstore(blobBaseFee.slot, calldataload(68))`

### Frequency

Not sure

### Code example to reproduce the issue:

See above

### Version:

0.10.0

### Relevant log output:

_No response_


Discussion:

Resolving patch:
diff --git a/slither/core/cfg/node.py b/slither/core/cfg/node.py
--- a/slither/core/cfg/node.py
+++ b/slither/core/cfg/node.py
@@ -11,6 +11,7 @@
     SolidityFunction,
 )
 from slither.core.expressions.expression import Expression
+from slither.core.expressions import CallExpression, Identifier, AssignmentOperation
 from slither.core.solidity_types import ElementaryType
 from slither.core.source_mapping.source_mapping import SourceMapping
 from slither.core.variables.local_variable import LocalVariable
@@ -898,6 +899,21 @@ def _find_read_write_call(self) -> None:  # pylint: disable=too-many-statements
                 # TODO: consider removing dependancy of solidity_call to internal_call
                 self._solidity_calls.append(ir.function)
                 self._internal_calls.append(ir.function)
+            if (
+                isinstance(ir, SolidityCall)
+                and ir.function == SolidityFunction("sstore(uint256,uint256)")
+                and isinstance(ir.node.expression, CallExpression)
+                and isinstance(ir.node.expression.arguments[0], Identifier)
+            ):
+                self._vars_written.append(ir.arguments[0])
+            if (
+                isinstance(ir, SolidityCall)
+                and ir.function == SolidityFunction("sload(uint256)")
+                and isinstance(ir.node.expression, AssignmentOperation)
+                and isinstance(ir.node.expression.expression_right, CallExpression)
+                and isinstance(ir.node.expression.expression_right.arguments[0], Identifier)
+            ):
+                self._vars_read.append(ir.arguments[0])
             if isinstance(ir, LowLevelCall):
                 assert isinstance(ir.destination, (Variable, SolidityVariable))
                 self._low_level_calls.append((ir.destination, str(ir.function_name.value)))


Test patch:
diff --git a/tests/e2e/detectors/test_data/constable-states/0.8.0/const_state_variables.sol b/tests/e2e/detectors/test_data/constable-states/0.8.0/const_state_variables.sol
--- a/tests/e2e/detectors/test_data/constable-states/0.8.0/const_state_variables.sol
+++ b/tests/e2e/detectors/test_data/constable-states/0.8.0/const_state_variables.sol
@@ -66,7 +66,7 @@ contract Good {
     uint immutable should_be_immutable_3 = 10 + block.number;
     B immutable should_be_immutable_4 = new B();
     uint immutable should_be_immutable_5;
-    
+    uint blobBaseFee;
 	constructor(uint b) {
 		should_be_immutable_5 = b;
 	}
@@ -74,5 +74,10 @@ contract Good {
     function getNumber() public returns(uint){
         return block.number;
     }
-
+    
+    function updateBlobBaseFee(uint _blobBaseFee) public {
+        assembly {
+            sstore(blobBaseFee.slot, _blobBaseFee)
+        }
+    }
 }
\ No newline at end of file
diff --git a/tests/e2e/detectors/test_data/constable-states/0.8.0/const_state_variables.sol-0.8.0.zip b/tests/e2e/detectors/test_data/constable-states/0.8.0/const_state_variables.sol-0.8.0.zip
Binary files a/tests/e2e/detectors/test_data/constable-states/0.8.0/const_state_variables.sol-0.8.0.zip and b/tests/e2e/detectors/test_data/constable-states/0.8.0/const_state_variables.sol-0.8.0.zip differ