Bird
Raised Fist0
Blockchain / Solidityprogramming~30 mins

Reentrancy attacks in Blockchain / Solidity - Mini Project: Build & Apply

Choose your learning style10 modes available
Understanding Reentrancy Attacks in Smart Contracts
📖 Scenario: You are learning about smart contracts on the Ethereum blockchain. One common security problem is the reentrancy attack, where a malicious contract repeatedly calls back into a vulnerable contract to drain funds.In this project, you will create a simple vulnerable contract, then add a fix to prevent reentrancy attacks.
🎯 Goal: Build a smart contract that holds Ether and allows withdrawals. First, create a vulnerable version that can be attacked by reentrancy. Then, add a guard to prevent the attack.
📋 What You'll Learn
Create a contract with a mapping to track user balances
Write a withdraw function that sends Ether to the user
Add a boolean lock variable to prevent reentrancy
Use the lock variable to guard the withdraw function
Print events to show when withdrawals happen
💡 Why This Matters
🌍 Real World
Smart contracts on blockchains hold real money. Preventing reentrancy attacks protects users' funds from being stolen.
💼 Career
Blockchain developers must understand and fix reentrancy vulnerabilities to build secure decentralized applications.
Progress0 / 4 steps
1
Create a vulnerable contract with balances
Create a Solidity contract called VulnerableBank. Inside it, declare a public mapping called balances that maps address to uint. Also, write a deposit function that is payable and adds msg.value to the sender's balance.
Blockchain / Solidity
Hint

Use mapping(address => uint) public balances; to store balances. The deposit function should be payable and add msg.value to balances[msg.sender].

2
Add a withdraw function vulnerable to reentrancy
Add a public function called withdraw that takes a uint amount. Inside, check that balances[msg.sender] is at least amount. Then, send amount Ether to msg.sender using call. Finally, subtract amount from balances[msg.sender]. Do not add any reentrancy protection yet.
Blockchain / Solidity
Hint

Use require to check balance. Use call to send Ether. Subtract amount from balance after sending.

3
Add a reentrancy guard using a lock variable
Add a private boolean variable called locked initialized to false. Modify the withdraw function to first check that locked is false, then set locked to true before sending Ether. After sending, set locked back to false. This prevents reentrancy.
Blockchain / Solidity
Hint

Use a boolean locked to block reentrant calls. Set it true before sending Ether and false after.

4
Add events and print withdrawal success
Declare an event called Withdrawal with parameters address indexed user and uint amount. Emit this event after a successful withdrawal inside the withdraw function. Finally, add a print statement that outputs "Withdrawal successful" after the event.
Blockchain / Solidity
Hint

Declare event Withdrawal(address indexed user, uint amount); and emit it after withdrawal. Use print("Withdrawal successful") to show success.

Practice

(1/5)
1. What is a reentrancy attack in blockchain smart contracts?
easy
A. An attack where a contract is called repeatedly before finishing its first call
B. An attack that steals private keys from a wallet
C. An attack that floods the network with transactions
D. An attack that changes the blockchain consensus rules

Solution

  1. Step 1: Understand the concept of reentrancy

    Reentrancy happens when a contract allows another call to itself before the first call finishes, causing unexpected behavior.
  2. Step 2: Identify the correct description

    An attack where a contract is called repeatedly before finishing its first call correctly describes repeated calls before finishing, which is the core of reentrancy attacks.
  3. Final Answer:

    An attack where a contract is called repeatedly before finishing its first call -> Option A
  4. Quick Check:

    Repeated calls before finish = Reentrancy attack [OK]
Hint: Look for repeated calls before state update to spot reentrancy [OK]
Common Mistakes:
  • Confusing reentrancy with key theft
  • Thinking it floods network instead
  • Mixing with consensus attacks
2. Which Solidity code snippet correctly prevents reentrancy by updating state before sending Ether?
easy
A. payable(msg.sender).transfer(amount); balances[msg.sender] = 0;
B. require(balances[msg.sender] > 0); payable(msg.sender).transfer(amount);
C. balances[msg.sender] = 0; payable(msg.sender).transfer(amount);
D. balances[msg.sender] += amount; payable(msg.sender).transfer(amount);

Solution

  1. Step 1: Identify the safe order of operations

    To prevent reentrancy, update the user's balance before sending Ether to avoid repeated withdrawals.
  2. Step 2: Check each option's order

    balances[msg.sender] = 0; payable(msg.sender).transfer(amount); updates balance first, then sends Ether, which is the correct pattern.
  3. Final Answer:

    balances[msg.sender] = 0; payable(msg.sender).transfer(amount); -> Option C
  4. Quick Check:

    Update state before transfer = Safe pattern [OK]
Hint: Always update balances before sending Ether to avoid reentrancy [OK]
Common Mistakes:
  • Sending Ether before updating balance
  • Not checking balance before transfer
  • Increasing balance instead of resetting
3. Consider this Solidity function snippet:
function withdraw(uint amount) public {
  require(balances[msg.sender] >= amount);
  payable(msg.sender).transfer(amount);
  balances[msg.sender] -= amount;
}
What is the likely outcome if this contract is attacked by a reentrancy exploit?
medium
A. The attacker can withdraw more than their balance multiple times
B. The contract will reject the withdrawal due to require failing
C. The contract will revert due to syntax error
D. The attacker cannot withdraw more than their balance

Solution

  1. Step 1: Analyze the order of operations in withdraw

    The contract sends Ether before reducing the balance, allowing reentrant calls to withdraw repeatedly.
  2. Step 2: Understand the attack effect

    Because balance is reduced after transfer, attacker can call withdraw again before balance updates, draining funds.
  3. Final Answer:

    The attacker can withdraw more than their balance multiple times -> Option A
  4. Quick Check:

    Transfer before balance update = Vulnerable to reentrancy [OK]
Hint: Check if balance updates happen after transfer to spot vulnerability [OK]
Common Mistakes:
  • Assuming require protects fully
  • Thinking syntax error occurs
  • Believing attacker can't withdraw extra
4. This Solidity function is vulnerable to reentrancy. What is the best fix?
function withdraw(uint amount) public {
  require(balances[msg.sender] >= amount);
  payable(msg.sender).transfer(amount);
  balances[msg.sender] -= amount;
}
medium
A. Add a loop to call transfer multiple times
B. Remove the require statement
C. Increase balances[msg.sender] after transfer
D. Move balances[msg.sender] -= amount; before transfer call

Solution

  1. Step 1: Identify vulnerability cause

    Balance is updated after sending Ether, allowing reentrant calls to exploit the contract.
  2. Step 2: Apply fix by reordering

    Moving balance update before transfer prevents reentrancy by blocking repeated withdrawals.
  3. Final Answer:

    Move balances[msg.sender] -= amount; before transfer call -> Option D
  4. Quick Check:

    Update state before transfer = Fix reentrancy [OK]
Hint: Update balances before sending Ether to fix reentrancy [OK]
Common Mistakes:
  • Removing require weakens security
  • Adding loops increases risk
  • Increasing balance after transfer worsens issue
5. You want to secure a smart contract against reentrancy attacks. Which combination of techniques is best practice?
hard
A. Allow multiple reentrant calls to improve performance
B. Update state before external calls and use a reentrancy guard modifier
C. Use only require statements without updating state
D. Send Ether first, then update state, and avoid using modifiers

Solution

  1. Step 1: Recall best practices for reentrancy protection

    Update contract state before external calls and use reentrancy guard modifiers to block repeated calls.
  2. Step 2: Evaluate options

    Update state before external calls and use a reentrancy guard modifier combines both safe state update order and reentrancy guard, providing strong protection.
  3. Final Answer:

    Update state before external calls and use a reentrancy guard modifier -> Option B
  4. Quick Check:

    State update + guard = Best reentrancy defense [OK]
Hint: Combine state update and guard modifier for strong defense [OK]
Common Mistakes:
  • Sending Ether before state update
  • Ignoring reentrancy guard usage
  • Allowing reentrant calls for speed
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard