I want to share a pretty important thing that you might not fully understand yet — that is, the reentrancy vulnerability in smart contracts. If you're developing dApps or working with blockchain, this is a must-know.



What is the basic problem of reentrancy? It occurs when a smart contract calls another contract, and that contract can call back into the original contract while it’s still executing. An attacker can exploit this window to steal funds.

Imagine ContractA has 10 Ether, and ContractB has sent 1 Ether to it. When ContractB calls the withdraw function, ContractA checks if the balance is greater than 0, and if so, sends Ether back. But here’s the issue — ContractA only updates the balance after sending the money. So, during the transfer, if ContractB has a fallback function, it can call the withdraw function of ContractA again. Since the balance hasn't been updated yet, the check will pass again, and it will receive another 1 Ether. This loop continues until ContractA runs out of funds.

I will show you three ways to protect your contract from this reentrancy attack.

The first way is to use the nonReentrant modifier. The idea is very simple — you lock the contract while the function is executing. If someone tries to call that function again, it will be rejected because the contract is locked. You must finish executing the code and then unlock it, at which point the check will fail if reentry is attempted.

The second way is to use the Checks-Effects-Interactions pattern. Instead of updating the balance after sending money, you update it immediately after the check but before the transfer. This way, even if another contract calls back, the balance is already zero, so the check will fail. That’s why the order is very important — check first, then update state, then interact with other contracts.

The third way is to create a separate GlobalReentrancyGuard, which is especially useful when multiple contracts interact. Instead of protecting individual functions, you create a shared guard contract that stores the lock state in one place. When any contract tries to call a protected function, it checks with this guard. If the guard indicates the contract is locked, the transaction is rejected. This method is very powerful because it prevents reentrancy not just within a single contract but across multiple contracts.

I recommend applying all three techniques depending on the situation. For withdrawal or asset transfer functions, always use nonReentrant or Checks-Effects-Interactions. And if your project involves a complex system of contracts, consider using GlobalReentrancyGuard as an additional layer of protection.

This is one of the most common vulnerabilities that can lead to significant losses, so understanding reentrancy thoroughly is extremely important if you want to write secure smart contracts.
XCH-5.23%
TRA-1.66%
XEM-2.43%
View Original
This page may contain third-party content, which is provided for information purposes only (not representations/warranties) and should not be considered as an endorsement of its views by Gate, nor as financial or professional advice. See Disclaimer for details.
  • Reward
  • Comment
  • Repost
  • Share
Comment
Add a comment
Add a comment
No comments
  • Pinned