The reentrancy family of attacks occur when a smart contract makes an external call to another untrusted contract before it resolves its own state. If the external contract contains a fallback function that makes recursive calls back into the original function, it can exploit the logic before the original contract completes execution. This was the root cause of the infamous 2016 DAO hack, and variations of this attack continue to appear in modern DeFi protocols.
Standard Reentrancy
This attack exploits the order of operations inside a contract, where a contract sends Ether before updating the sender’s balance. An attacker can recursively call the withdraw function to drain funds before the balance is correctly updated. This vulnerability devastated the DAO in 2016, causing the loss of over $60 million in Ether and leading to the Ethereum chain split.
Read-Only Reentrancy
This form of reentrancy doesn’t directly steal funds but manipulates onchain data by calling view functions during an inconsistent state. While not directly financially exploitable in isolation, it can compromise decision making in other contracts, especially ones depending on balance snapshots.
Cross Function Reentrancy
Instead of repeatedly calling the same function, this attack uses reentrancy to jump between multiple vulnerable functions that share or rely on the same state variables. This allows attackers to manipulate state in unexpected ways that aren’t protected by simple reentrancy guards.
Cross Contract Reentrancy
Cross-contract reentrancy occurs when a contract calls an external contract which then calls back into a different vulnerable function of the original contract. Because the call path isn’t always obvious, these vulnerabilities are harder to detect and defend without centralized guards or careful sequencing of state changes.
Reentrancy via Modifier
Modifiers used for security, like mutexes, can themselves be reentrant if not properly implemented. If an external call is made inside the modifier or between the modifier and the function logic, reentrancy can still be exploited despite apparent safeguards.
ERC-721 and ERC-1155 SafeTransfer Reentrancy
ERC-721 and ERC-1155 tokens invoke hooks like onERC721Received and onERC1155Received when transferring tokens to contracts. If the recipient contract’s hook is malicious, it can trigger reentrancy back into the token contract, especially if that contract interacts with external systems such as lending or marketplaces. Improper handling of these hooks has led to stolen NFTs and drained protocols.
Defense and Best Practices
Always update contract state before making external calls. Use reentrancy guards like OpenZeppelin’s ReentrancyGuard to enforce a non-reentrant state. Audit all external calls, including those within modifiers and hooks, for potential cycles. Avoid callbacks entirely if possible or whitelist only trusted targets. Design your contract assuming the callee can execute arbitrary logic and always treat msg.sender and msg.value with caution during fallback or receive calls.
References
https://github.com/Quillhash/Solidity-Attack-Vectors
https://consensys.io/diligence/blog/2019/09/stop-using-soliditys-transfer-now
https://rekt.news/daohack
https://blog.openzeppelin.com/compound-vulnerability-retro
https://halborn.com/blog/post/defi-hack-deep-dive-creams-130m-flash-loan-attack
A Historical Collection of Reentrancy Attacks / pcaversaccio / github /


