Static_Analysis
Smart Contract Security Analysis with Slither
Overview
In this security research exercise, I analyzed three example Solidity contracts using Slither — a static analysis tool for smart contracts.
The goal was to:
- Detect vulnerabilities
 - Understand the risks
 - Show how to write safer smart contracts
 - Practice presenting findings to recruiters
 
Contracts Under Review
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/*
 Your original Counter — unchanged
*/
contract Counter {
    int256 private count;
    address public owner;
    constructor() payable {
        count = 0;
        owner = msg.sender;
    }
    function increment() public {
        count += 1;
        owner = msg.sender;
    }
    function decrement() public {
        count -= 1;
        owner = msg.sender;
    }
    function getCount() public view returns (int256) {
        return count;
    }
}
/*
 Simple DeFi: a minimal deposit/withdraw vault — INTENTIONALLY VULNERABLE
 - Uses .call and updates state AFTER sending ETH → classic reentrancy pattern
 - Public mapping shows balances
*/
contract SimpleVault {
    mapping(address => uint256) public balanceOf;
    function deposit() external payable {
        balanceOf[msg.sender] += msg.value;
    }
    function withdraw(uint256 amount) external {
        require(balanceOf[msg.sender] >= amount, "insufficient");
        // Vulnerable: external call before state update
        (bool ok, ) = payable(msg.sender).call{value: amount}("");
        require(ok, "send failed");
        balanceOf[msg.sender] -= amount; // state update after external call
    }
}
/*
 Safer DeFi version:
 - Checks-Effects-Interactions pattern (state update BEFORE external call)
*/
contract SafeVault {
    mapping(address => uint256) public balanceOf;
    function deposit() external payable {
        balanceOf[msg.sender] += msg.value;
    }
    function withdraw(uint256 amount) external {
        require(balanceOf[msg.sender] >= amount, "insufficient");
        // Effects first
        balanceOf[msg.sender] -= amount;
        // Interaction after effects
        (bool ok, ) = payable(msg.sender).call{value: amount}("");
        require(ok, "send failed");
    }
}
My Command Line Process
I used Slither to run the analysis in my local environment:
root@lenova:~/practice# slither .
'forge clean' running (wd: /root/practice)
'forge config --json' running
'forge build --build-info --skip */test/** */script/** --force' running (wd: /root/practice)
INFO:Detectors:
Reentrancy in SimpleVault.withdraw(uint256) (src/Counter.sol#44-50):
        External calls:
        - (ok,None) = address(msg.sender).call{value: amount}() (src/Counter.sol#47)
        State variables written after the call(s):
        - balanceOf[msg.sender] -= amount (src/Counter.sol#49)
        SimpleVault.balanceOf can be used in cross function reentrancies.
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities
INFO:Detectors:
Contract locking ether found:
        Contract Counter has payable functions but no way to withdraw the ether.
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#contracts-that-lock-ether
INFO:Detectors:
Version constraint ^0.8.0 contains known severe issues.
INFO:Detectors:
Low level call in SimpleVault.withdraw(uint256)
Low level call in SafeVault.withdraw(uint256)
INFO:Slither:. analyzed (3 contracts with 93 detectors), 5 result(s) found
Findings & Analysis
1. Reentrancy Vulnerability — SimpleVault (High Risk)
- Found in:
(bool ok, ) = payable(msg.sender).call{value: amount}("");
balanceOf[msg.sender] -= amount; - Why bad: State change happens after sending ETH, allowing malicious fallback calls to exploit the function.
 - Fix: Use Checks-Effects-Interactions pattern or ReentrancyGuard.
 
2. Locked Ether — Counter (Medium Risk)
- Contract can receive ETH (payable constructor) but no function to withdraw it.
 - Effect: ETH sent can never be recovered.
 
3. Outdated Solidity Version (Medium Risk)
^0.8.0includes known compiler bugs.- Fix: Upgrade to latest stable version (e.g., 
^0.8.21). 
4. Low-Level Call Usage (Low Risk / Informational)
.callis used in both withdraw functions.- Risk: Can trigger arbitrary fallback logic.
 - Recommendation: Use cautiously, always handle return values.
 
Summary Table
| Issue Detected | Contract | Severity | Impact | 
|---|---|---|---|
| Reentrancy | SimpleVault | High | Theft of ETH | 
| Locked Ether | Counter | Medium | Funds locked | 
| Outdated Solidity Version | All | Medium | Compiler bugs | 
| Low-Level Call Usage | Vaults | Low | Unexpected behavior | 
Lessons Learned
- Always update state before external calls.
 - Provide ETH recovery methods for payable contracts.
 - Use the latest compiler versions.
 - Treat 
.callwith caution.