Smart contracts automate and secure blockchain transactions without intermediaries, making them essential for Web3 and decentralized apps. However, they are prone to vulnerabilities. In Q1 2024, smart contract exploits led to almost $45 million in losses across 16 incidents, averaging $2.8 million per exploit. This article explores the top 10 most critical smart contract vulnerabilities and how to mitigate them.
Types of Smart Contract Vulnerabilities
Smart contract vulnerabilities can be categorized into several types, each posing significant risks to blockchain applications. Understanding these vulnerabilities is essential for developing robust and secure smart contracts.
Vulnerability
Description
Reentrancy
Exploits the contractβs external call feature, allowing repeated calls before the initial function completes.
Integer Overflow/Underflow
Results from arithmetic operations that exceed the data typeβs storage capacity.
Improper Access Control
Allow unauthorized users to access or modify contract data or functions (such as unprotected withdrawal) due to inadequate access restrictions
Front-Running
Exploits the time gap between the transactionβs broadcast and its inclusion in the blockchain.
Denial of Service (DoS)
Making the contract unavailable or unresponsive by consuming all available gas or causing transactions to continually fail.
Weak Randomness
Using insecure block-related methods to generate random numbers, which can be manipulated.
Vulnerable External Calls
Risks associated with making external calls without proper validation.
Logic Errors
Includes flaws in the contractβs logic leading to unexpected behaviors.
Oracle Manipulation
Distortion of oracle price feeds or other off-chain data to steal assets.
Flashloan Attacks
The use of uncollateralized loans to manipulate markets or exploit contract vulnerabilities.
How Smart Contract Vulnerabilities Occur
Smart contract vulnerabilities typically arise from common coding mistakes or logical errors. Issues like unchecked external calls, improper validation, and arithmetic errors can lead to exploits. Letβs delve into specific vulnerabilities and their mitigations.
1. Reentrancy
A reentrancy attack occurs when a contract makes an external call to another contract before updating its state. The called contract can then call back into the original contract, causing unexpected behavior.
Reentrancy Types
There are several types of reentrancy attacks:
Single-Function Reentrancy: The attacker repeatedly calls the same function.
Cross-Function Reentrancy: A vulnerability in one function can exploit other functions sharing the same state variables.
Cross-Contract Reentrancy: Two contracts sharing the same state fail to update immediately before a cross-contract call.
Read-Only Reentrancy: Reentering a view function can cause inconsistent state values, leading other protocols to read incorrect data and take unintended actions.
The vulnerability arises when we send the user their requested amount of ether. In this scenario, the attacker exploits the withdraw() function. Because their balance hasnβt been reset to 0, they can transfer tokens despite already having received some. The attack involves invoking the withdraw function in the victimβs contract. Upon receiving the tokens, the receive function inadvertently triggers the withdraw function again. As the check passes, the contract sends tokens to the attacker, subsequently activating the receive function.
Crypto Hacks Involving Reentrancy Attacks
Rari Capital Hack ($80M)
On April 30, 2022, Rari Capital, a decentralized lending and borrowing platform, was hacked due to a flaw in its borrowed code from Compound. The borrow function lacked proper checks-effects-interactions patterns. The attacker exploited this by:
Obtaining a 150,000,000 USDC flashloan.
Depositing it into the fUSDC-127 contract.
Calling the vulnerable borrow function to borrow assets.
The function transferred the borrowed amount before updating the accountBorrows mapping. Without a reentrancy guard, the attacker repeatedly called the borrow function before the mapping updated, draining $80 million.
The hacker borrowed assets using a flashloan and ran the doTransferOut function five times in a loop. After repaying the flashloan, they took the remaining funds and disappeared with $80 million. Transaction: ββ0xab486012
Orion Protocol ($3M)
On February 2, 2023, the Orion protocol was hacked due to a reentrancy vulnerability in one of its core contracts, resulting in a $3 million loss. ββThe attacker exploited the depositAsset() method of the ExchangeWithOrionPool contract, which lacked reentrancy protection. They created a fake token (ATK) with a self-destruct feature leading to the transfer() function.
Reentrancy Mitigation
Use the Checks-Effects-Interactions pattern to ensure state changes occur before external calls.
In general, to prevent reentrancy attacks, Web3 projects can:
Ensure all state changes happen before calling external contracts, i.e., update balances or code internally before calling external code.
Use function modifiers that prevent reentrancy. OpenZeppelin provides a ReentrancyGuard contract with this functionality.
Employ the pull payment method.
Implement emergency stop patterns to prevent multiple executions of vulnerable code.
Conduct thorough smart contract testing and auditing.
2. Integer Overflow/Underflow
Integer overflow and underflow occur when arithmetic operations exceed the storage capacity of the data type, leading to unexpected results.
Underflow occurs when a value is decreased below zero, while overflow occurs when it exceeds its maximum value. These vulnerabilities can lead to unexpected behavior in smart contracts, potentially resulting in financial losses or system failures.
Consider a uint8 variable, which can hold a maximum of 8 bits. This means the highest number it can store is represented in binary as 11111111 (or in decimal as 2^8 β 1 = 255). In the event of underflow, subtracting 1 from a uint8 set to 0 will result in its value wrapping around to 255. Conversely, overflow occurs when attempting to add 1 to a uint8 set to 255, causing the value to reset back to 0.
Code Example Of Integer Overflow/Underflow Vulnerability
contract MyContract {
Β Β Β Β uint256 public a = type(uint256).min; // Minimum value for uint256, which is 0
Β Β Β Β uint256 public b = type(uint256).max; // Maximum value for uint256, which is 2^256 - 1
Β Β Β Β function add() external {
Β Β Β Β Β Β Β Β // b == 115792089237316195423570985008687907853269984665640564039457584007913129639935
Β Β Β Β Β Β Β Β b = b + 1; // This causes an integer overflow
Β Β Β Β Β Β Β Β // After incrementing, b wraps around to 0
Β Β Β Β Β Β Β Β // b == 0
Β Β Β Β }
Β Β Β Β function substract() external {
Β Β Β Β Β Β Β Β // a == 0
Β Β Β Β Β Β Β Β a = a - 1; // This causes an integer underflow
Β Β Β Β Β Β Β Β // After decrementing, a wraps around to the maximum uint256 value
Β Β Β Β Β Β Β Β // a == 115792089237316195423570985008687907853269984665640564039457584007913129639935
Β Β Β Β }
}
Crypto Hacks Involving Integer Overflow/Underflow
Poolz Finance Hack ($390K)
On March 15th, 2023, Poolz Finance contracts were hacked, resulting in a loss of at least $390K across BSC and Polygon due to an integer overflow vulnerability in the unaudited LockedControl smart contract. The attacker exploited the overflow by manipulating the GetArraySum() method, which increased the sum beyond its maximum limit, allowing them to withdraw excess tokens into their wallet.
PoWHC Hack ($800K)
Proof of Weak Hands Coin (PoWHC), a Ponzi scheme itself, was exploited due to an integer underflow vulnerability, allowing a hacker to steal 866 ETH. The vulnerability in the βapproveβ function of the ERC-20 implementation led to the balance of a second account being incorrectly adjusted, resulting in an inflated balance. By manipulating the transferFrom() and transferTokens() functions, the attacker caused the second accountβs balance to underflow to 2Β²β΅βΆ-1, enabling the theft.
Integer Overflow/Underflow Mitigation
With the release of Solidity 0.8, this concern has been addressed. The compiler now automatically verifies each arithmetic operation for overflow and underflow, and if detected, it throws an error. This alleviates the burden on developers, as they no longer need to manually handle these issues.
For Solidity under version 0.8, use the SafeMath library to prevent overflow and underflow. This library provided functions to safeguard against overflow and underflow vulnerabilities, ensuring the integrity of arithmetic operations in smart contracts.
using SafeMath for uint256;
function transfer(address _to, uint256 _value) public {
Β Β Β Β balances[msg.sender] = balances[msg.sender].sub(_value);
Β Β Β Β balances[_to] = balances[_to].add(_value);
}
3. Improper Access Control
An access control vulnerability allows unauthorized users to access or modify a contractβs data or functions. These arise when the code fails to restrict access based on permissions. In smart contracts, access control issues can affect governance and critical functions like minting tokens, voting, withdrawing funds, pausing/upgrading contracts, and changing ownership.
Common Access Control Vulnerabilities
Missed Modifier Validations: Missing validations in critical functions can lead to contract compromise or fund loss.
Incorrect Modifier Names: Errors in modifier names can bypass controls, risking fund loss or unauthorized changes.
Overpowered Roles: Excessive privileges create vulnerabilities; use the least privilege principle.
Code Example Of Improper Access Control
function mint(address account, uint256 amount) public {
Β Β Β Β // No proper access control is implemented for the mint function
Β Β Β Β _mint(account, amount);
}
Crypto Hacks Involving Improper Access Control
HospoWise Hack
HospoWise was hacked due to a public burn function, allowing anyone to burn tokens. The codeβs burn function lacked access control, enabling attackers to burn all Hospo tokens on UniSwap, causing inflation and draining the pool for ETH.
Prevention: Proper access control, such as onlyOwner, or making the function internal.
Rubixy Hack
Rubixy was exploited due to a constructor naming error. The function Fal1out was meant to be the constructor but was callable by anyone, allowing attackers to claim ownership and drain funds.
Prevention: Use proper constructor syntax and careful contract naming.
Improper Access Control Mitigation
Grant only the minimum access levels needed for entities to perform their tasks β Principle of Least Privilage (POLP). This principle helps prevent unauthorized parties from performing destructive actions, such as draining funds or altering critical variables.
Implement PoLP by using access control modifiers like onlyOwner from OpenZeppelinβs Ownable contract or by using role-based access control (RBAC) to define specific roles with distinct permissions.
In the code above, RBAC assigns user permissions based on predefined roles, providing granular control. It supports multiple roles, like onlyAdminRole and onlyModeratorRole, enhancing security by limiting access to necessary functions. OpenZeppelinβs AccessControl contract simplifies RBAC implementation in smart contracts.
4. Front-Running Attack
Front-running occurs when a malicious actor preempts a transaction by submitting a similar one with a higher gas fee. Since June 2020, Maximum Extractable Value traders operating bots (aka MEV bots) have profited over $1 billion on Ethereum, BSC, and Solana, often harming retail investors.
Three Types of Front-Running Attacks
Displacement: Using higher gas fees to prioritize their transaction.
Suppression: Flooding the network with high-fee transactions to delay others.
Insertion: Sandwiching a victimβs transaction between two of their own to profit from price changes.
Front-Running Mitigation
Use commit-reveal schemes to obscure bid details until after the bidding period.
Vulnerable Implementation
function placeBid(uint256 _bid) public {
Β Β Β Β require(_bid > highestBid);
Β Β Β Β highestBid = _bid;
}
To protect swapping applications, implement a slippage restriction between 0.1% and 5%, depending on network fees and swap size. This minimizes slippage, defending against front-runners who exploit higher rates, thus safeguarding your trades and reducing predatory risks.
DoS attacks can disrupt contract functionality by exploiting reverts, external call failures, and gas limit issues, making it unavailable to legitimate users.
DoS with Unexpected Revert
When a contract operation fails, it reverts changes. The EVM uses REVERT (0xFD) and INVALID (0xFE) opcodes to handle these errors, with REVERT returning the remaining gas to the caller and INVALID not returning any gas.
DoS with Unexpected Revert Example
The unexpected revert occurs when the contract attempts to send 1 ether using the call method. If the recipient is a contract that reverts upon receiving Ether, the transaction fails, preventing the beneficiary flag from being reset. This can lead to a DoS condition, blocking further withdrawals if the same address repeatedly attempts to withdraw.
Use pull over push payment patterns to prevent DoS. The pull pattern shifts the responsibility of withdrawing funds onto the recipient, preventing the contract from being locked due to failed transfers. A fully mitigated code would store pending withdrawals and allow users to claim them.
External calls can fail accidentally or deliberately, causing a DoS condition.
External Call Failure Mitigation
Let users withdraw funds rather than push them to them automatically.
Avoid combining multiple calls in a single transaction, especially in loops.
Assume external calls can fail.
Implement logic to handle failed calls.
Gas Limit Vulnerabilities
Large arrays or loops can exceed the block gas limit, causing a DoS condition.
Gas Limit Vulnerabilities Mitigation
Avoid looping over large arrays.
Plan for operations to take multiple blocks and transactions if necessary.
6. Weak Randomness
Generating random numbers on Ethereum is challenging due to its deterministic nature. Solidity relies on pseudorandom factors, and complex calculations are costly regarding gas.
Weak Random Generation Methods
Smart contract developers often use insecure block-related methods to generate random numbers, such as the current block timestamp, difficulty, number, address of the current miner, or the hash of a given block. However, these methods can be insecure because miners can manipulate them, affecting the contractβs logic.
function guess(uint256 _guess) public {
Β Β Β Β Β Β Β Β uint256 answer = uint256(keccak256(abi.encodePacked(block.timestamp, block.difficulty, msg.sender)));
}
Weak Randomness Mitigation
Using Oracles: Employ external sources of randomness like Chainlink VRF, which provides provably fair and verifiable random numbers.
Commitment Schemes: Use commit-reveal approaches, which have applications in coin flipping, zero-knowledge proofs, and secure computation (e.g., RANDAO).
Signidice Algorithm: Use cryptographic signatures suitable for PRNG in applications involving two parties.
7. Vulnerable External Calls
Making external calls without proper validation, like unchecked calls or calls to arbitrary addresses, can lead to unexpected behavior or security risks.
Unchecked External Calls
The function doesnβt verify the callβs success or failure. Even if the external call fails, the transaction continues, which can lead to unexpected behavior or vulnerabilities.
function externalCall(address _to) public {
Β Β Β Β (bool success, ) = _to.call("");
Β Β Β Β require(success);
}
Calls to arbitrary addresses refer to interactions with external addresses that are not predetermined or trusted. Attackers can exploit this flaw to run unauthorized code, extract assets, or disrupt the contractβs functionality.
Crypto Hacks Involving Vulnerable External Calls
Dexible Exploit ($2M)
On Feb 20, 2023, the Dexible DEX aggregator and execution management systemβs self-swapping function was exploited for its external call vulnerability, which allowed users to define a router contract.
Instead of a safe&valid DEX, a hacker made a contract to call a malicious ERC20 contract and drained $2M worth of tokens. The crucial part is the contracts were not audited.
contract maliciousRouter {
Β Β Β Β ...
Β Β Β Β //Instead of a validated router contract, the hacker implements this tricky function and makes Dexible contract to transfer its assets to this malicious contract.
Β Β Β Β function transfer() external {
Β Β Β Β Β Β Β Β IERC20(USDC).transferFrom(msg.sender, address(this), IERC20(USDC).balanceOf(msg.sender));
Β Β Β Β }
}
Vulnerable External Calls Mitigation
Use caution when making external calls: Calls to untrusted contracts can execute malicious code. Treat every external call as a potential security risk and follow best practices to minimize danger.
Mark untrusted contracts: Clearly name variables, methods, and contract interfaces to indicate potential risks when interacting with external contracts.
Avoid state changes after external calls: Malicious code can hijack control flow during external calls, leading to vulnerabilities like reentrancy. Avoid state changes after making external calls.
Do not use transfer() or send(): .transfer() and .send() forward exactly 2,300 gas, which may not be enough for recipients due to changing gas costs. Use .call() instead and check return values.
Handle errors in external calls: Use low-level call methods cautiously and always check return values to handle failures.
Favor pull over push for external calls: Isolate each external call into its own transaction, especially for payments. Let users withdraw funds rather than push them automatically to avoid gas limit issues.
Do not delegatecall to untrusted code: Using delegatecall with untrusted contracts can lead to state changes and potential loss of contract balance.
8. Logic Errors
Logic errors in smart contracts can lead to unintended behaviors, compromising security and functionality.
Logic Error Example
The function blindly adds the provided amount to the senderβs balance without validation, leading to potential issues like overflow and invalid inputs.
function updateBalance(int256 _amount) public {
Β Β Β Β balances[msg.sender] += _amount;
}
Reasons for Logic Errors
Developer Overload: The developers may have been overburdened with tasks and missed this validation step.
Lack of Expertise: Not enough knowledge of best practices and potential pitfalls in smart contract developing.
Insufficient Testing: The function may not have undergone thorough testing to catch this logic error.
Logic Error Mitigation
The general idea is to implement thorough testing and code reviews to detect and fix logic errors.
For example, the mitigated code adds a validation check to ensure the amount is positive before updating the balance, preventing overflow and invalid input issues.
Oracles are the blockchainβs gateway to the real world. They connect smart contracts to off-chain data (real-world events, price feeds, random number generation). However, oracle manipulation can significantly distort market prices through methods like spoofing, ramping, bear raids, cross-market manipulation, wash trading, and frontrunning.
Crypto Hacks Involving Oracle Manipulation
Inverse Finance ($15.6M)
Attackers manipulated the price of the INV token using SushiSwapβs TWAP oracle, borrowing $15.6M by depositing inflated INV tokens as collateral. Relying on a single oracle was a major problem.
Lodestar ($6.5M)
A bad actor manipulated the price oracle of plvGLP collateral, enabling them to drain the lending pools and profit approximately $6.5 million. The core vulnerability was in how the GLPOracle calculated the price of plsGLP. The attacker manipulated the price by increasing the total assets via the donate function, which pushed the price higher and allowed the attacker to borrow more than the true value of their collateral.
BonqDAO ($1.8M)
Polygon DeFi protocol BonqDAO fell victim to a price oracle hack due to a smart contract code error. The attacker stole 100 million $BEUR stablecoins and 120 million $WALBT. The exploit was enabled by ββa vulnerability inside the smart contract for price feed that supplies Bonq protocol with the ALBT price from the Tellor Oracle.
AaveV3 (Prevented)
A vulnerability in the fallback Oracle allowed attackers to set arbitrary asset prices, posing a significant security risk. A third-party audit prevented the possible hack.
Oracle Manipulation Mitigation
Use Reliable Oracles: Implement robust, decentralized oracles like Chainlink to minimize manipulation risk. Consider using VWAP (Volume-weighted average price) instead of TWAP (Time-weighted average price) for more accurate and manipulation-resistant prices, as VWAP reflects the asset price across various trading environments.
Implement Monitoring: Set up tools like Hacken Extractor to detect and alert on anomalous activities quickly. Continuous monitoring can help identify suspicious patterns or attempts to manipulate oracle prices.
Check and Validate Inputs: Ensure that all inputs, especially those affecting prices, are validated and resistant to manipulation. Proper validation can prevent attackers from exploiting price calculation mechanisms.
Flashloan attacks use uncollateralized loans to manipulate markets or exploit contract vulnerabilities within a single transaction block. In Q1 2024, 10 high-profile flashloan attacks resulted in $33M in losses. Flashloans are not inherent vulnerabilities within the contract; rather, attackers use them to increase leverage and magnify the impact of existing smart contract weaknesses.
Crypto Hacks Involving Flashloan Attacks
Beanstalk ($181M)
Beanstalk, a stablecoin protocol with a governance structure, was exploited due to inadequate checks against flashloans in its smart contract. The attacker took a massive flashloan, gained a 78% supermajority, and used the emergencyCommit function to pass a unanimous proposal, draining funds from the protocol.
function emergencyCommit(uint32 bip) external {
Β Β require(isNominated(bip), "Governance: Not nominated.");
Β Β // Requires 1 day to be passed (getGovernanceEmergencyPeriod=1day)
Β Β require(
Β Β block.timestamp >= timestamp(bip).add(C.getGovernanceEmergencyPeriod()), Β Β "Governance: Too early.");
Β Β require(isActive(bip), "Governance: Ended.");
Β Β //Any vote can be executed if proposer has the super majority(getGovernanceEmergencyThreshold=67%)
Β Β require(
Β Β bipVotePercent (bip). greaterThanOrEqualTo(C.getGovernanceEmergencyThreshold()), Β "Governance: Must have super majority." );
Β Β _execute(msg.sender, bip, false, true);
}
Sonne Finance ($20M)
On May 16, 2024, Sonne Finance was exploited for $20 million due to a known vulnerability in Compound V2 forks. Despite warnings from previous incidents, the protocol failed to implement comprehensive safeguards, allowing an attacker to manipulate governance permissions and drain funds using flash loans.
Flashloan Attack Mitigation
Audit Smart Contracts: Conduct security audits regularly to identify and fix vulnerabilities. Comprehensive security audits can uncover potential weaknesses in contract logic and implementation.
Requiring collateral for loans makes it more expensive for hackers to borrow assets.
Implement limits on the size of flash loans that can be taken out, which can help mitigate large-scale attacks.
Add time locks to smart contracts to hinder the ability to repay flashloans too quickly, giving developers time to detect and prevent attacks.
Projects with governance voting systems must implement an anti-flashloan mechanism to prevent exploiters from using flashloans to gain the majority of the voting power.
Security patterns are essential for developing robust smart contracts. Key patterns include:
Checks-Effects-Interactions Pattern: Implement the Checks-Effects-Interactions pattern to ensure state changes occur before external calls and utilize the Reentrancy Guard to prevent reentrancy attacks.
Mutex Pattern: Prevents reentrancy by locking the contract during execution.
Balance Limit Pattern: Limits a contractβs balance to reduce risk.
Best Practices for Secure Smart Contract Development
By adhering to these best practices, developers can build a robust defense system that fortifies their smart contractsβ security:
Reuse Audited Libraries: Use well-established libraries like OpenZeppelin, and thoroughly read documentation to understand and properly use the code.
Test Your Code: Aim for 100% branch coverage, use multiple user tests, and employ test fuzzing (e.g., Foundry framework) to detect errors.
Apply for an Audit: Consider professional audits, such as from Hacken, to identify potential vulnerabilities.
Use SafeERC20 Library: When dealing with ERC20 tokens, utilize the SafeERC20 library to handle operations that could fail.
Employ a MultiSig Wallet: MultiSig wallets can be used for contract ownership to increase security and reduce single points of failure.
Use Locked Pragma Versions: Lock Solidity versions to avoid known bugs and ensure stability (e.g., use 0.8.10 instead of ^0.8.10).
Carefully Interact with Third-Party Contracts: Verify third-party contracts for bugs, audits, and proper usage to minimize external calls.
Exercise Caution with Delegatecall: Understand that delegatecall executes code in the calling contractβs context, preserving msg.sender and msg.value.
Use msg.sender for Authentication: Prefer msg.sender over tx.origin to enhance security and prevent authorization vulnerabilities.
Avoid Arithmetic Overflow and Underflow: Use Solidity versions above 0.8 or employ the SafeMath library for earlier versions.
Utilize Static Code Analyzers: Use tools like Slither for static code analysis to detect vulnerabilities and enhance code quality.
Validate Function Arguments: Ensure all user-provided arguments are validated to prevent malicious input.
Beware of Integer Division Rounding: Use multipliers for precision or store numerator and denominator separately.
Explicitly Mark Visibility: To avoid unintended access, define visibility for functions and storage variables.
Avoid using extcodesize to check for EOAs. extcodesize returns zero during contract construction, which can lead to potential issues.
Restrict Access to Critical Functions: Implement access controls to restrict important functions.
Use Emergency Stop Pattern: Implement Pausable contracts to halt operations in emergencies.
Prefer Pull Over Push Pattern: Use the pull pattern to handle payments securely.
Given the extensive array of potential vulnerabilities outlined β from specific examples spotlighted to over 30 additional issues identified in our smart contract audit checklist β the threat landscape in the blockchain domain is complex and multifaceted. Smart contract developers are pivotal in creating cutting-edge applications and establishing security measures to protect these contracts from evolving threats. Their challenging task is to stay ahead of these risks, ensuring their applicationsβ security, integrity, and trustworthiness.
Web3 projects must prioritize security in their blockchain apps. By adhering to guidelines and proactively addressing vulnerabilities, developers can build user trust, protect assets, and contribute to the stability and growth of the blockchain ecosystem. Prioritizing security safeguards individual projects and strengthens the entire decentralized finance space. Letβs work together to create a safer and more secure blockchain environment for everyone.
The blockchain industry has been grappling with scalability issues, which have hindered widespread adoption due to its technical constraints. As the demand for blockchain, decentralized applications (dApps), and transactions increases, the limitations of existing networks become increasingly apparent. High transaction fees and network congestion have plagued platforms like Ethereum, hampering their ability to support large-scale
The experimental semi-fungible token standard, ERC-404, combines elements from ERC-20 and ERC-721 tokens. Despite rising popularity, it has yet to secure an official Ethereum Improvement Proposal (EIP) designation. However, its unique attributes, such as enabling fractional ownership of NFTs and enhancing liquidity, coupled with the potential for automated NFT minting and burning processes, suggest a
Decentralized applications (dApps) are software that run on a decentralized network, often using blockchain technology. These applications can serve various purposes for end users, such as brokers, art collectors, traders, investors, and documents of public trust. However, their functionality and value attract malicious groups aiming to exploit vulnerabilities for financial gain. This article explores real-world examples of dApp security breaches, their attack vectors, and the lessons learned.