Common Solidity Mistakes That Cause Security Issues | PandaSecurity
Web3 Security

Common Solidity Mistakes That Cause Security Issues

PandaSecurity Team •
#Solidity Security#Smart Contract Audit#Web3 Security
Solidity smart contract security review concept

Smart contracts are the foundation of many Web3 applications, including DeFi protocols, NFT platforms, and decentralized applications. However, unlike traditional software, smart contract vulnerabilities can directly affect user assets and protocol funds.

At PandaSecurity, we review smart contracts from an attacker’s perspective. During security reviews, we often find that many risks are not caused by extremely complex code. Instead, they come from simple mistakes in logic, assumptions, and contract design.

This article explains some of the most common Solidity mistakes that can introduce security risks.

1. Missing or Incorrect Access Control

Access control determines who can execute sensitive functions.

Many contracts contain privileged operations such as:

A common mistake is forgetting to restrict these functions.

Example:

function setFee(uint256 newFee) external {
    fee = newFee;
}

Without proper authorization, any user could modify important protocol settings.

A safer design should include appropriate permission checks:

function setFee(uint256 newFee) external onlyOwner {
    fee = newFee;
}

However, security reviews should not only check whether a modifier exists. Auditors should also verify:

Incorrect access control remains one of the most common causes of smart contract security issues.

2. Unsafe External Contract Calls

Smart contracts frequently interact with external contracts, including tokens, oracles, and other protocols.

External calls should always be treated as potentially dangerous because the called contract can execute unexpected logic.

A classic example is updating state after making an external call:

function withdraw() external {
    uint256 amount = balances[msg.sender];

    payable(msg.sender).call{value: amount}("");

    balances[msg.sender] = 0;
}

The problem is that the user-controlled contract receives execution control before the internal balance is updated.

A safer approach follows the Checks-Effects-Interactions pattern:

function withdraw() external {
    uint256 amount = balances[msg.sender];

    balances[msg.sender] = 0;

    payable(msg.sender).call{value: amount}("");
}

The key security principle is simple:

Do not trust external calls.

3. Incorrect ERC20 Token Assumptions

Many Solidity developers assume every ERC20 token behaves exactly the same.

In reality, tokens may have different implementations:

For example, a protocol that calculates accounting based only on requested transfer amounts may become inconsistent if the actual received amount is different.

When interacting with ERC20 tokens, developers should carefully handle transfer results and understand token behavior.

Security reviews often focus on whether protocol assumptions match real token behavior.

4. Weak Oracle Integration

Many DeFi protocols rely on external price information.

The oracle itself may be secure, but the integration logic can still introduce vulnerabilities.

Common mistakes include:

For lending protocols, exchanges, and derivatives platforms, incorrect price handling can affect:

Oracle security requires reviewing both the data source and how the protocol consumes that data.

5. Precision and Rounding Errors

Solidity uses integer arithmetic, which means division can lose precision.

Example:

uint256 reward = amount * 5 / 100;

In financial applications, small rounding differences can become important when repeated over many transactions.

Common areas requiring attention include:

Developers should carefully consider rounding direction and ensure accounting remains consistent.

6. Upgradeability Risks

Upgradeable contracts introduce additional complexity.

Proxy-based systems require careful management of:

A secure implementation can still become vulnerable if the upgrade mechanism is poorly designed.

Security reviews should analyze the complete upgrade architecture, not only the implementation logic.

7. Ignoring Protocol Invariants

Reading individual functions is not always enough to discover smart contract vulnerabilities.

Auditors often define important rules that should always remain true.

Examples:

These rules are known as invariants.

Testing invariants through fuzzing and manual analysis can reveal unexpected edge cases.

8. Treating Smart Contracts as Isolated Systems

Modern Web3 protocols are highly interconnected.

A contract may interact with:

A function that appears safe alone may become dangerous when combined with another component.

Attackers usually analyze the complete system, not just a single contract.

How PandaSecurity Reviews Smart Contracts

At PandaSecurity, we combine manual security research with automated analysis tools to identify realistic attack paths.

Our security review approach focuses on:

Security is not only about finding known vulnerability patterns. It is about understanding how a protocol can fail under unexpected conditions.

Final Thoughts

Most Solidity security issues are not caused by complicated programming mistakes.

They usually come from incorrect assumptions:

Smart contract security should be considered from the beginning of development.

A professional security review provides another perspective before attackers find these weaknesses.

PandaSecurity helps Web3 teams improve contract security through smart contract auditing and security research.

Related articles

← Back to Blog