Top 10 Smart Contract Vulnerabilities You Need to Know About
In the ever-evolving landscape of blockchain technology, smart contracts have revolutionized how transactions and agreements are executed. However, their potential is matched by their vulnerabilities. While offering unparalleled benefits, smart contracts’ immutability and decentralized nature also make them prime targets for exploitation. Understanding and addressing these smart contract vulnerabilities cannot be overstated, as they can lead to significant financial losses and undermine the integrity of blockchain ecosystems.
Drawing insights from sources such as the OWASP Smart Contract Top 10, DeFi Llama’s major hack statistics, rekt.news and BlockApex’s extensive audit experience, we present a comprehensive list of the most common and critical vulnerabilities found in smart contracts. This curated list aims to equip developers, auditors, and blockchain enthusiasts with the knowledge to secure their projects against prevalent threats.
Reentrancy Attacks
A reentrancy attack in smart contracts occurs when an external call is made to another contract before the first contract’s state has been fully updated. This allows the external contract to call back into the original function before the state update is completed, potentially causing unexpected and harmful behavior. Essentially, it’s a state synchronization problem where the contract’s state is manipulated before it can be properly updated.
Types of Reentrancy Attacks
- Single-Function Reentrancy: This occurs when a function in a contract calls itself repeatedly without updating its state. This is the simplest form of reentrancy.
- Cross-Function Reentrancy: This happens when one function calls another function within the same contract that shares state, and the state is not updated properly between calls.
- Cross-Contract Reentrancy: This involves multiple contracts where one contract calls a function in another contract that calls back into the first contract, leading to state inconsistencies.
- Cross-Chain Reentrancy: This occurs when interactions happen between smart contracts on different blockchain networks, complicating the state synchronization.
- Read-Only Reentrancy: This occurs when an external call is made to another contract, but the called contract’s function does not modify its state. Instead, it reads data and reenters the calling contract, potentially causing unexpected behavior.
Example of a Vulnerable Smart Contract
Here’s a simplified example of a smart contract vulnerable to a reentrancy attack:
In this contract, the withdraw function is vulnerable because it sends Ether to the caller before updating the balances.
How an Attacker Exploits Reentrancy
- Step 1: The attacker deposits Ether into the vulnerable contract.
- Step 2: The attacker creates a malicious contract that calls the withdraw function of the vulnerable contract.
- Step 3: The withdraw function sends Ether to the attacker’s contract and, before updating the balance, the malicious contract’s fallback function calls withdraw again.
- Step 4: This process repeats, draining the contract’s funds before the balance is updated.
Attacker’s Malicious Contract
Case Studies
- The DAO Hack (2016): The most infamous reentrancy attack that led to the theft of approximately $60 million in Ether, which resulted in a hard fork of the Ethereum blockchain.
- Lendf.me (2020): An attacker exploited a reentrancy vulnerability to steal $25 million from the DeFi protocol.
- Cream Finance (2021): Over $130 million was stolen due to a reentrancy attack exploiting the protocol’s flash loan feature.
Mitigation Strategies
- Checks-Effects-Interactions (CEI) Pattern:
The Checks-Effects-Interactions (CEI) pattern is a best practice in smart contract development that helps prevent reentrancy attacks. It involves structuring functions to follow a specific order: performing all checks first, then updating the state, and finally interacting with external contracts. This order ensures that the contract’s state is always updated before any external calls are made, reducing the risk of reentrancy.
Here’s a breakdown of how the CEI pattern works, using the withdraw function as an example:
- Reentrancy Guards:
Use Openzeppelin’s reentrancy guard to prevent a function from being called multiple times.
Tools to identify the issue:
References:
- BlockApex Audit Report
- https://blockapex.io/labs/rari-capital-hack-analysis-poc/
- https://blockapex.io/labs/orion-protocol-hack-analysis/
- https://blockapex.io/labs/dforce-network-hack-analysis/
- https://blockapex.io/labs/cream-finance-hack-analysis/
Flashloan-Based Price Manipulation
Flashloan-based price manipulation represents one of the most high-profile and damaging types of attacks in decentralized finance (DeFi). These attacks have resulted in substantial financial losses, undermining the integrity of various DeFi platforms.
Understanding Flashloan Price Manipulation
Flashloans allow users to borrow large amounts of cryptocurrency without collateral, provided the loan is repaid within the same transaction. This unique feature is exploited in flashloan attacks to manipulate asset prices and execute profitable trades based on these manipulated prices.
When a smart contract queries the price of an asset, it assumes the queried contract is immune to manipulation. Attackers exploit this assumption by using flashloans to create artificial buying or selling pressure, thereby manipulating the asset’s price.
How Flashloan Attacks Work
A typical flashloan attack involves three main steps:
- Borrowing: The attacker takes out a flashloan, borrowing a substantial amount of cryptocurrency.
- Manipulating: Using the borrowed funds, the attacker manipulates the price of a targeted asset by executing trades that significantly alter the asset’s price on decentralized exchanges.
- Repaying: The attacker repays the flashloan within the same transaction block, securing the manipulated profits.
This process allows the attacker to exploit temporary price discrepancies without needing to provide collateral.
Notable Examples of Flashloan Attacks
- Euler Finance (March 2023): Euler Finance suffered a $197 million loss due to a flashloan attack that exploited an error in the platform’s rate calculation.
- Cream Finance (October 2021): A complex attack on Cream Finance resulted in a $130 million loss, leveraging flashloans to manipulate the value of yUSDVault shares.
Mitigation
To mitigate the risk of flashloan-based price manipulation, DeFi developers should consider the following best practices:
- Diversified Oracles: Use multiple price oracles to provide more accurate and tamper-resistant price data.
- Reentrancy Guards: Implement reentrancy guards to prevent unexpected contract calls.
- Access Control: Use access control mechanisms to limit who can execute critical functions within the smart contract.
- Thorough Audits: Conduct comprehensive third-party audits to identify and mitigate potential vulnerabilities.
Time-Weighted Average Price (TWAP): Implement TWAP mechanisms to reduce the impact of short-term price manipulation.
References
- https://blockapex.io/labs/beanstalk-hack-analysis-poc/
- https://blockapex.io/labs/cream-finance-hack-analysis/
- https://blockapex.io/labs/euler-finance-hack-analysis/
Access Control Exploit
Access control exploits occur when smart contracts fail to restrict who can call certain sensitive functions properly. This allows unauthorized users to perform critical operations such as transferring funds, changing ownership, or modifying contract parameters. Proper access control ensures that only authorized entities can interact with specific functionalities or modify important data within a smart contract.
Example of an Access Control Vulnerability:
The 88mph Function Initialization Bug: In June 2021, a vulnerability was found in the 88mph platform’s CRV and yaLink pools. The vulnerability involved an unprotected init() function that allowed users to reinitialize the contract, granting them administrative privileges. This flaw could have led to the theft of $6.5 million in tokens.
Here’s a simplified version of the vulnerable contract:
In this example, the init function can be called by anyone at any time, allowing users to set themselves as the owner and take control of minting and burning tokens.
Steps an Attacker Takes to Exploit the Vulnerability
- Identify the Vulnerability: The attacker identifies the unprotected init function.
- Call the Init Function: The attacker calls the init function, setting themselves as the owner.
- Gain Control: As the new owner, the attacker now controls the mint and burn functions.
- Exploit: The attacker mints many tokens to their address or burns tokens from other users’ addresses, leading to significant financial loss.
Real-Life Case Study
88mph Function Initialization Bug: A whiteHat security researcher found an unprotected init function in several 88mph pools. This vulnerability could have allowed an attacker to mint and burn NFTs at will, potentially losing $6.5 million. The issue was promptly reported, and a whitehat operation was conducted to secure user funds.
Mitigations
To prevent access control vulnerabilities like the one in 88mph, developers should follow these best practices:
- Use Constructors for Initialization: Constructors are functions automatically called once when a contract is deployed and cannot be called again. This ensures secure initialization.
- Add an onlyOwner Modifier: Restrict sensitive functions so only the owner can call them.
- Use an initializer Modifier: Ensure initialization functions can only be called once.
- Established Patterns: Use established patterns like Ownable and Role-Based Access Control
References
- BlockApex Audit Report
- https://blockapex.io/labs/dexible-hack-analysis/
- https://blockapex.io/labs/merlin-dex-hack-analysis/
Front-Running Attacks
Front-running attacks are a critical vulnerability in blockchain systems, particularly in smart contracts, where malicious actors exploit the transaction ordering to their advantage. These attacks occur when an attacker observes a pending transaction and takes advantage of the time delay before it is included in a block by submitting their own transaction with a higher gas fee. This incentivizes miners to prioritize the attacker’s transaction, thereby allowing the attacker to manipulate the transaction outcome.
Example of Front-Running Vulnerability
One of the critical findings by BlockApex in an audit involved a front-running vulnerability in the CollectionOffer contract. The vulnerability allowed an attacker to reduce the payout to sellers during the fulfillment of offers. Here is an example of a similar vulnerable contract:
Steps for an Attacker to Exploit the Vulnerability
- Initial Offer: The offerer submits an offer for an item at a high value (e.g., 20 ETH) by calling offerItem(itemId, 20 ether).
- Offer Acceptance: The seller sees the high offer and decides to accept it by calling fulfillItem(itemId).
- Malicious Update: Before the seller’s transaction completes, the offerer quickly updates the offer price to a very low value (e.g., 1 wei) by calling updateOffer(itemId, 1).
- Transaction Completion: The seller’s transaction to fulfill the offer goes through, but because the offerer updated the price just before the fulfillment, the seller receives only the reduced amount (1 wei) instead of the initially offered 20 ETH.
Real-Life Case Study: DODO DEX Hack (March 2021)
On March 8, 2021, the DODO DEX experienced a significant hack, resulting in the theft of approximately $3.8 million in cryptocurrency from several of its crowdfunding pools. The attackers exploited a vulnerability in the init() function of the DODO V2 Crowdpooling smart contract, allowing them to call the function multiple times with different parameters. The attack involved creating a counterfeit token, manipulating the contract’s reserve variable, and using a flash loan to drain real tokens from the pools. Interestingly, the original attacker was also a victim of front-running bots, which intercepted and executed transactions before the attacker, capturing some of the stolen funds. Approximately $3.1 million of the stolen assets were eventually returned, highlighting the importance of robust access control and thorough security audits in smart contract development.
Mitigation
To prevent this front-running vulnerability, the offer price should be verified at the time of fulfillment to ensure it has not been altered since the offer was made
-
- Commit-Reveal Scheme: Use a two-step process where users first commit to a value with a hash, and then reveal the value in a later transaction. This prevents attackers from seeing the actual value until it is too late to front-run.
- Gas Price Limits: Set limits on the gas price that can be used in transactions to prevent attackers from paying exorbitant fees to front-run legitimate users
- Off-Chain Order Matching: Use off-chain mechanisms to match orders and then settle them on-chain, reducing the risk of front-running since the critical parts of the transaction occur off-chain.
- Randomized Delays: Introduce random delays in transaction processing to make it harder for attackers to predict when their front-running transactions will be included in a block.
References
- BlockApex Audit Report
- https://blockapex.io/labs/impact-of-blockchain-on-bug-fixing/
- https://blockapex.io/labs/flashbots-and-mevs-a-beginners-guide/
Oracle/Price Manipulation Attacks
Oracle/Price manipulation is a significant vulnerability in decentralized finance (DeFi) that exploits the reliance on external data sources, known as oracles, to obtain asset prices. Attackers manipulating these oracles can create false price information, leading to severe financial consequences.
What is a Blockchain Oracle?
A blockchain oracle is a service that provides smart contracts with external data, enabling them to execute transactions based on real-world information. Oracles bridge blockchains and off-chain data, bringing external insights into the blockchain ecosystem. Examples of popular oracles include Chainlink, Pyth, Tellor, and Uniswap’s time-weighted average price (TWAP) mechanism.
How Oracle/Price Manipulation Attacks Work
Oracle manipulation attacks occur when attackers exploit vulnerabilities in the Oracle’s price feed mechanism. This typically involves manipulating the data that oracles use to report asset prices. Here’s a simplified step-by-step explanation:
- Identify Vulnerable Oracle: Attackers look for oracles that rely on data from low-liquidity sources or have a single point of failure.
- Manipulate Market Data: Using techniques like flash loans, attackers artificially inflate or deflate the price of an asset in a decentralized exchange (DEX) or other low-liquidity pool.
- Update Oracle Feed: The manipulated price is then fed into the oracle, which updates its data based on the falsified market conditions.
- Exploit Protocol Logic: DeFi protocols relying on this manipulated price make incorrect calculations, such as overvaluing collateral or triggering unwanted liquidations.
Example of Oracle/Price Manipulation Attack
Case Study 1: BonqDAO Hack
Incident: On February 1, 2023, BonqDAO was hacked, resulting in a $120 million loss due to a price oracle manipulation.
Attack Steps:
- Initial Setup: The attacker identified the vulnerable submitValue function in the WALBT/BEUR TellorFlex pair contract (Tellor allows reporting of off-chain prices).
- Inflated Price Report: The attacker reported an inflated price for the WALBT token, allowing them to borrow a large amount of BEUR, the protocol’s stablecoin.
- Borrowing: Using the inflated price, the attacker borrowed more BEUR than the collateral should have allowed.
- Price Deflation: The attacker then deflated the WALBT price, making other users’ positions under-collateralized.
- Liquidation: The attacker liquidated these positions, acquiring their collateral at a discount.
Vulnerable Function:
Case Study 2: Mango Markets Hack
Incident: In October 2022, an oracle manipulation attack exploited Mango Markets for $117 million.
Attack Steps:
- Initial Setup: The attacker created two large accounts on Mango Markets.
- Artificial Inflation: The attacker used one account to buy a large amount of Mango’s native token (MNGO) and sold it to the other account, artificially inflating its price.
- Borrowing: With the inflated MNGO value, the attacker borrowed significant other assets from Mango’s liquidity pools.
- Price Correction: The inflated price was corrected naturally over time, but by then, the attacker had already siphoned off a substantial amount of assets.
Mitigation
- Time-Weighted Average Price (TWAP): Smooth out price volatility.
- Multiple Data Sources: Aggregates data from multiple sources to reduce manipulation risks.
- Access Controls: Restricts who can update critical parameters.
- Decentralized Oracles: Using oracles like Chainlink that aggregate prices from multiple sources.
- Circuit Breakers: Pausing contract operations during abnormal price movement
- Oracle Dispute Mechanisms: Allowing participants to dispute and correct inaccurate data.
References
- https://blockapex.io/labs/bonqdao-hack-analysis/
- https://blockapex.io/labs/cream-finance-hack-analysis/
Missing or Inadequate Input Validation
Improper input validation arises when smart contracts do not sufficiently validate and sanitize user inputs. This can lead to several types of attacks, such as injection attacks, arithmetic overflows, and manipulation of contract logic. Proper input validation ensures that all inputs conform to expected formats, values, and types before the contract processes them.
Example Vulnerable Contract
Issue:
- The contract allows transferring tokens to the same address (from and to being the same), leading to balance inflation.
Attack Steps
- Identification: The attacker identifies that the transfer function allows transferring tokens to the same address without proper validation.
- Exploitation: The attacker repeatedly transfers tokens to themselves, exploiting the lack of validation to inflate their token balance.
Case Studies
Super Sushi Samurai Hack:
Overview
On March 21, 2024, Super Sushi Samurai (SSS) was exploited due to a transfer logic bug that allowed infinite token minting. This led to a loss of over 1,310 ETH, worth approximately $4.6 million.
Attack Details
The SSS token contract was vulnerable in the transfer function, which did not adequately check that the sender and receiver addresses differed. This allowed an attacker to transfer tokens to themselves, effectively doubling their token holdings with each transfer.
Mitigation
- Comprehensive Input Validation: Implement thorough input validation routines to ensure all inputs meet expected criteria. This includes checking data types, ranges, and formats.
- Boundary Checks: Validate that numerical inputs fall within acceptable boundaries and that no operations exceed or fall below these limits. Ensure transfer amounts are within the sender’s balance.
- Sanitization of Inputs: Sanitize inputs to prevent injection attacks. This can involve removing or escaping potentially harmful characters and ensuring inputs conform to expected patterns.
- Employ Fuzzing and Symbolic Execution: Use these tools to automatically generate various inputs and test the contract’s responses. This helps identify edge cases and potential vulnerabilities that might not be apparent through manual testing.
References
- BlockApex Audit Report
- https://blockapex.io/labs/sushiswap-hack-ana/
- https://blockapex.io/labs/platypus-finance-hack-analysis/
Incorrect Calculation and Rounding Error Vulnerabilities
Incorrect calculations occur when mathematical operations in smart contracts are performed incorrectly, leading to unexpected or erroneous results. These errors can result from incorrect assumptions about data precision, failure to account for edge cases, or handling overflows and underflows improperly. Rounding errors, on the other hand, happen when floating-point arithmetic is used without accounting for precision, causing financial discrepancies or exploitation opportunities.
Vulnerable Contract Example
Exploitation
The attacker claimed rewards for the same epochs multiple times, exploiting the lack of checks for reused epochs and draining the platform of funds.
Case Study: Level Finance Hack
Overview
On May 1, 2023, Level Finance, a DeFi platform on the BNB Chain, was exploited due to business logic and incorrect Calculation vulnerability in its referral reward system. This hack resulted in a loss of $1.1 million and a significant drop in the LVL token price.
Mitigation
- Unit Testing and Fuzzing: Implement unit testing and fuzzing or symbolic execution to identify and prevent edge cases from creeping into the codebase. These methods help ensure the code handles all possible input scenarios robustly.
- Formal Verification: Utilize formal verification for mathematical equations to guarantee the states that can exist within the contract, ensuring correctness in all scenarios.
- Secure Mathematical Libraries: Use well-tested and secure mathematical libraries or built-in functions provided by the blockchain platform for performing calculations. These libraries often include protections against common errors such as overflow or underflow.
- Fixed-Point Arithmetic: Employ fixed-point arithmetic or libraries designed for precise numerical operations to handle decimal calculations accurately, avoiding the imprecision associated with floating-point arithmetic.
References
Signature Replay Attacks
Overview
Signature replay attacks are a significant security concern in blockchain systems. They allow attackers to reuse a previously valid signature to perform unauthorized actions. These attacks exploit vulnerabilities in the way signatures are validated and managed, leading to potential financial loss and unauthorized access. Common issues that lead to signature replay attacks include reusable nonces, cross-chain replay vulnerabilities, missing parameters, lack of expiration, unchecked ecrecover() returns, and signature malleability.
Description
A signature replay attack occurs when an attacker reuses a previously valid signature to repeat an action without the user’s consent. This can happen if the smart contract does not properly manage nonces, chain IDs, or other unique transaction identifiers. These attacks exploit the fact that a valid signature can be used multiple times if there are no mechanisms to prevent reuse.
Vulnerable Contract Example
code from Ondo’s code4rena contest:
Attack Steps
- Sign Message: The user signs a message to authorize KYC approval.
- Submit Signature: The user submits the signature to the addKYCAddressViaSignature function, granting KYC status.
- Replay Attack: If the KYC status is revoked later, an attacker can reuse the same signature to restore it without the user’s consent, as the contract does not use nonces to prevent signature reuse.
Case Study: Polygon Double-Spending Attack
In October 2021, Polygon’s Plasma Bridge was found to have a double-spending attack due to a bug in the WithdrawManager contract. The flaw allowed an attacker to reuse a signature to execute multiple withdrawals from the bridge, potentially causing a loss of up to $22.3 million. The vulnerability was swiftly addressed, and the whitehat hacker was awarded a record $2 million bounty for reporting the issue.
Mitigation
To prevent signature replay attacks, the following measures should be implemented:
- Nonces: Use unique nonces for each signature to ensure that each signature can only be used once. Incorporate nonces into the signed message and store them on-chain to prevent reuse.
- Chain ID: Include the chain ID in the signed message to prevent cross-chain replay attacks.
- Parameter Validation: Ensure all parameters required for validation are included in the signed message.
- Expiration: Add an expiration time to signatures, so they are only valid for a limited period.
- ecrecover Checks: Always check the return value of ecrecover() to ensure it returns a valid address.
- Signature Malleability: Use libraries like OpenZeppelin’s ECDSA.sol to prevent signature malleability by validating the s value and ensuring it is in the lower range
References
- Blockapex Audit Report
- Signature Replay attacks
- https://rekt.news/nomad-rekt/
- https://rekt.news/polynetwork-rekt/
Vulnerability in Uninitialized Proxy Contracts
An uninitialized proxy contract refers to a situation where the proxy’s state variables, such as ownership and permissions, are not set up correctly before deployment or use. This can lead to severe security issues, as attackers might exploit these uninitialized states to gain control over the contract or execute unauthorized actions. To prevent such vulnerabilities, developers must ensure that all critical state variables are initialized properly and that initialization checks are in place before the proxy contract is used in any capacity.
Case Study: Wormhole Uninitialized Proxy Bug
In February 2022, a critical vulnerability was discovered in the Wormhole core bridge contract on Ethereum. The bug was due to an uninitialized proxy implementation, allowing an attacker to control the contract and potentially lock up user funds. A whitehat responsibly disclosed this vulnerability, preventing any loss of funds. Wormhole quickly fixed the issue and paid a record $10 million bounty to the whitehat for the discovery.
Mitigation
- Initialize All State Variables: Ensure all critical state variables, including ownership and permissions, are initialized before deploying the contract.
- Use Constructor Functions: Implement constructor or initialization functions that set all necessary state variables.
- Perform Initialization Checks: Include checks within the proxy contract to verify that all required variables are initialized before executing critical functions.
References
- OpenZepplin Proxy Vulnerability
- https://blog.openzeppelin.com/the-state-of-smart-contract-upgrades?utm_source=immunefi
- https://medium.com/immunefi/wormhole-uninitialized-proxy-bugfix-review-90250c41a43a
Exploiting Decentralized Governance
Governance attacks can manifest in multiple forms, such as influencing proposal outcomes without achieving a quorum, bypassing necessary voting steps, or directly altering the votes of other participants. These attacks undermine the decentralized governance framework, potentially leading to centralized control or financial exploitation. DAOs rely on distributed decision-making among token holders and are particularly susceptible to these vulnerabilities. Effective prevention requires robust, transparent governance models and secure voting mechanisms.
Case Study: Beanstalk Governance Attack
In a notable example, an attacker exploited Beanstalk’s governance protocol using flash loans. By borrowing significant voting power, the attacker passed a malicious proposal to transfer funds and then repaid the loan within the same transaction. This attack demonstrated the critical need for robust governance security measures.
Mitigation
- Secure Voting Systems: Implement tamper-resistant voting mechanisms using cryptographic techniques to ensure vote integrity.
- Token Distribution: Promote fair and decentralized token distribution to avoid concentration of voting power.
- Token Locking and Vesting: Use token vesting or lock-up periods to discourage short-term manipulative behaviors.
References
Conclusion
Securing smart contracts against vulnerabilities is paramount in the evolving landscape of blockchain technology. From reentrancy attacks and flashloan price manipulation, to access control exploits and oracle manipulation, understanding and mitigating these threats is essential for protecting financial assets and maintaining trust in decentralized systems.
Developers can significantly reduce the risk of exploitation by employing best practices such as diversified oracles, reentrancy guards, robust access controls, and comprehensive third-party audits. Security audit firms, tools and platforms like BlockApex, rekt.news, and Solodit provide invaluable resources for staying informed about the latest vulnerabilities, analyzing past hacks, and ensuring smart contracts are thoroughly audited and secure.
Addressing these vulnerabilities vigilantly and proactively will help create a safer and more resilient blockchain ecosystem in the future.
Read More:
Top Industry Leading Smart Contract Auditing Tools