Generated: 2026-04-18T16:30:33.747Z ChainProof version: 0.1.0 Files scanned: 1
| Severity | Count |
|---|---|
| 🔴 Critical | 3 |
| 🟠 High | 2 |
| 🟡 Medium | 1 |
| 🟢 Low | 0 |
| 🔵 Info | 0 |
| ⛽ Gas | 0 |
| Total | 6 |
⚠️ This contract has critical or high severity findings. Do not deploy to mainnet without addressing these issues.
Scanned with ChainProof AST engine (Slither not available)
- ID:
CP-107(SWC-107) - Location: Line 41
Description
Function "withdraw" makes an external call before updating state variables. An attacker can re-enter the function before the state is updated, potentially draining funds (e.g. the DAO hack).
Recommendation
Apply the Checks-Effects-Interactions pattern: update all state variables before making any external calls. Alternatively, use OpenZeppelin's ReentrancyGuard modifier.
Affected Code
function withdraw(uint256 amount) external {
require(balances[msg.sender] >= amount, "Insufficient balance");
// ❌ External call BEFORE state update — classic reentrancy
(bool success, ) = msg.sender.call{value: amount}("");
require(success, "Transfer failed");
// State updated AFTER call — attacker can re-enter before this line
balances[msg.sender] -= amount;
totalDeposited -= amount;
}- ID:
CP-107(SWC-107) - Location: Line 59
Description
Function "sendReward" makes an external call before updating state variables. An attacker can re-enter the function before the state is updated, potentially draining funds (e.g. the DAO hack).
Recommendation
Apply the Checks-Effects-Interactions pattern: update all state variables before making any external calls. Alternatively, use OpenZeppelin's ReentrancyGuard modifier.
Affected Code
function sendReward(address recipient) external onlyOwner {
// ❌ .send() return value ignored — failure is silently swallowed
recipient.call{value: rewardPool}("");
rewardPool = 0;
}- ID:
CP-107(SWC-107) - Location: Line 66
Description
Function "transferOwnership" makes an external call before updating state variables. An attacker can re-enter the function before the state is updated, potentially draining funds (e.g. the DAO hack).
Recommendation
Apply the Checks-Effects-Interactions pattern: update all state variables before making any external calls. Alternatively, use OpenZeppelin's ReentrancyGuard modifier.
Affected Code
function transferOwnership(address newOwner) external {
require(tx.origin == owner, "Not owner");
owner = newOwner;
}- ID:
CP-115(SWC-115) - Location: Line 29
Description
tx.origin refers to the original external account that initiated the transaction, not the immediate caller. A phishing contract can exploit this to perform unauthorized actions on behalf of the victim.
Recommendation
Replace tx.origin with msg.sender for authorization checks. If you need to distinguish EOAs from contracts, use msg.sender == tx.origin as a secondary check, not the primary guard.
Affected Code
require(tx.origin == owner, "Not owner");- ID:
CP-115(SWC-115) - Location: Line 67
Description
tx.origin refers to the original external account that initiated the transaction, not the immediate caller. A phishing contract can exploit this to perform unauthorized actions on behalf of the victim.
Recommendation
Replace tx.origin with msg.sender for authorization checks. If you need to distinguish EOAs from contracts, use msg.sender == tx.origin as a secondary check, not the primary guard.
Affected Code
require(tx.origin == owner, "Not owner");- ID:
CP-104(SWC-104) - Location: Line 61
Description
.call() and .send() return a boolean indicating success. Ignoring this return value means failures are silently swallowed, potentially leaving the contract in an inconsistent state.
Recommendation
Always check the return value: (bool success, ) = addr.call{value: amount}(""); require(success, "Transfer failed");. Prefer .transfer() for simple ETH sends if reentrancy is not a concern.
Affected Code
recipient.call{value: rewardPool}("");This report was generated by ChainProof. It is not a substitute for a manual security audit by a qualified professional.