You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Issue: External call made before state variables are updated. Attacker can recursively call the function to drain funds.
Solution: Use the checks-effects-interactions pattern: verify, update state, then call external contracts. Or use OpenZeppelin's ReentrancyGuard modifier.
Examples:
function withdraw(uint amount) public { (bool success,) = msg.sender.call{value: amount}(""); balances[msg.sender] -= amount; }
WRONG: Call before state update. RIGHT: Update balances first, then call.
🚨 Integer Overflow/Underflow (Line 2)
Severity:CRITICAL
Issue: Solidity versions before 0.8.0 do not have built-in overflow/underflow protection. Integer arithmetic can wrap around causing unexpected behavior.
Solution: Upgrade to Solidity 0.8.0 or later which has built-in overflow checks. Or use SafeMath library from OpenZeppelin.
Examples:
Solidity < 0.8: uint256 balance = 0; balance -= 1; // wraps to max uint256
Issue: Critical functions lack access control checks. Anyone can call functions meant only for specific users (owner, admin, etc).
Solution: Add access control modifiers like onlyOwner, onlyAdmin, or use role-based access control (RBAC). Use OpenZeppelin's Ownable or AccessControl.
Examples:
WRONG: function mint(address to, uint amount) public { balances[to] += amount; }
RIGHT: function mint(address to, uint amount) public onlyOwner { balances[to] += amount; }
⚡ Timestamp Dependency (Line 85)
Severity:MEDIUM
Issue: Smart contracts relying on block.timestamp for critical logic are vulnerable. Miners can manipulate timestamps within a small range (usually ±15 seconds).
Solution: Use block.number instead of block.timestamp for ordering events. Or accept that timestamps can vary by ~15 seconds and design logic accordingly.
Examples:
RISKY: if (block.timestamp > deadline) { ... }
BETTER: if (block.number > blockDeadline) { ... }
⚡ Missing Zero Address Check (Line 43)
Severity:MEDIUM
Issue: Transfers to address(0) are mistakes that lose funds forever. Code should validate recipient is not the zero address.
Solution: Add explicit check: require(to != address(0), 'Cannot transfer to zero address')
Examples:
WRONG: function transfer(address to, uint amount) public { balances[msg.sender] -= amount; balances[to] += amount; }
RIGHT: function transfer(address to, uint amount) public { require(to != address(0), 'Invalid address'); balances[msg.sender] -= amount; balances[to] += amount; }
Issue: Solidity versions before 0.8.0 do not have built-in overflow/underflow protection. Integer arithmetic can wrap around causing unexpected behavior.
Solution: Upgrade to Solidity 0.8.0 or later which has built-in overflow checks. Or use SafeMath library from OpenZeppelin.
Examples:
Solidity < 0.8: uint256 balance = 0; balance -= 1; // wraps to max uint256
Issue: Critical functions lack access control checks. Anyone can call functions meant only for specific users (owner, admin, etc).
Solution: Add access control modifiers like onlyOwner, onlyAdmin, or use role-based access control (RBAC). Use OpenZeppelin's Ownable or AccessControl.
Examples:
WRONG: function mint(address to, uint amount) public { balances[to] += amount; }
RIGHT: function mint(address to, uint amount) public onlyOwner { balances[to] += amount; }
Issue: Using tx.origin for authorization instead of msg.sender. Attackers can spoof tx.origin via phishing attacks or delegatecall chains. tx.origin represents the original EOA, not the immediate caller.
Solution: Always use msg.sender for access control. Never use tx.origin for authorization. tx.origin should only be used in exceptional cases where you understand the security implications.
Issue: Low-level calls (.call, .delegatecall) return a boolean indicating success. Not checking this return value can lead to silent failures. If the call fails, execution continues as if nothing happened.
Solution: Always check the return value: require(success, 'call failed'). Or use high-level functions (transfer, send) which revert on failure. Never ignore the success boolean.
Issue: Solidity versions before 0.8.0 do not have built-in overflow/underflow protection. Integer arithmetic can wrap around causing unexpected behavior. Example: 0 - 1 = max uint256.
Solution: Upgrade to Solidity 0.8.0 or later which has built-in overflow checks. For older contracts, use SafeMath library from OpenZeppelin for all arithmetic operations.
Examples:
Solidity < 0.8: uint256 balance = 0; balance -= 1; // wraps to max uint256
Issue: Transfers to address(0) are mistakes that lose funds forever. Code should validate recipient is not the zero address. This is especially critical in token contracts.
Solution: Add explicit check: require(to != address(0), 'Cannot transfer to zero address'). Apply this check to all functions that accept an address as recipient.
Examples:
WRONG: function transfer(address to, uint amount) public { balanceOf[msg.sender] -= amount; balanceOf[to] += amount; }
RIGHT: function transfer(address to, uint amount) public { require(to != address(0), 'Invalid address'); balanceOf[msg.sender] -= amount; balanceOf[to] += amount; }
⚠️Missing Access Control (Line 46)
Severity:HIGH
Issue: Critical functions lack access control checks. Anyone can call functions meant only for specific users (owner, admin, etc). This is especially dangerous for mint, burn, and administrative functions.
Solution: Add access control modifiers like onlyOwner, onlyAdmin, or use role-based access control (RBAC). Use OpenZeppelin's Ownable or AccessControl. Verify sender is authorized before executing critical operations.
Examples:
WRONG: function transferFrom(address from, address to, uint amount) external { balanceOf[from] -= amount; balanceOf[to] += amount; }
RIGHT: function transferFrom(address from, address to, uint amount) external { require(msg.sender == from || allowance[from][msg.sender] >= amount, 'Not authorized'); ... }
⚠️Unchecked Account Injection (Line 24)
Severity:HIGH
Issue: Using extcodesize checks for contract detection can be unreliable. Contracts can self-destruct, making the check return false positives. Using contract existence checks for security decisions is dangerous.
Solution: Avoid relying on isContract() for security decisions. If you must check contract existence, be aware of edge cases. Use robust methods or implement proper token callback standards (ERC223, ERC777).
Examples:
WRONG: if (isContract(to)) { /* do something */ }
RISKY: Using assembly { size := extcodesize(account) } for authorization
⚠️Missing Balance Validation (Line 21)
Severity:HIGH
Issue: Functions that deduct balances don't verify sufficient balance exists first. In pre-0.8 Solidity, this causes silent underflow instead of reverting. Funds can be transferred when balance is insufficient.
Solution: Always check balance before subtraction: require(balanceOf[msg.sender] >= amount, 'Insufficient balance'). Upgrade to Solidity 0.8+ which automatically reverts on underflow.
Examples:
WRONG: function transfer(address to, uint amount) { balanceOf[msg.sender] -= amount; balanceOf[to] += amount; }
RIGHT: function transfer(address to, uint amount) { require(balanceOf[msg.sender] >= amount, 'Insufficient'); balanceOf[msg.sender] -= amount; balanceOf[to] += amount; }
⚡ Missing Allowance Validation (Line 39)
Severity:MEDIUM
Issue: transferFrom doesn't validate that the spender has sufficient allowance before executing the transfer. Combined with underflow vulnerabilities, this can cause silent failures.
Solution: Always check allowance before spending: require(allowance[from][msg.sender] >= amount, 'Allowance exceeded'). Use standard ERC20 implementation or OpenZeppelin's SafeERC20.
Examples:
WRONG: function transferFrom(address from, address to, uint amount) { allowance[from][msg.sender] -= amount; balanceOf[from] -= amount; balanceOf[to] += amount; }
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.