Challenge - 5 Problems
Withdrawal Pattern Master
Get all challenges correct to earn this badge!
Test your skills under time pressure!
❓ Predict Output
intermediate2:00remaining
Understanding withdrawal pattern output
What is the output of this Solidity contract snippet when calling
withdraw() after depositing 5 ether?Blockchain / Solidity
pragma solidity ^0.8.0; contract Withdrawal { mapping(address => uint) public balances; function deposit() public payable { balances[msg.sender] += msg.value; } function withdraw() public { uint amount = balances[msg.sender]; require(amount > 0, "No balance to withdraw"); (bool success, ) = msg.sender.call{value: amount}(""); require(success, "Transfer failed"); balances[msg.sender] = 0; } }
Attempts:
2 left
💡 Hint
Think about the order of state update and transfer in the withdrawal function.
✗ Incorrect
The contract sends the ether first and then sets the user's balance to zero. Since the transfer is done via call and the balance is reset after, the user receives the full amount and the balance is cleared.
🧠 Conceptual
intermediate1:30remaining
Why use withdrawal pattern in smart contracts?
Which of the following best explains why the withdrawal pattern is recommended over direct transfers in smart contracts?
Attempts:
2 left
💡 Hint
Think about security risks when sending ether directly.
✗ Incorrect
Withdrawal pattern avoids reentrancy attacks by letting users pull their funds instead of contracts pushing funds directly, which can trigger malicious fallback functions.
🔧 Debug
advanced2:30remaining
Identify the bug in this withdrawal pattern implementation
What is the main bug in this Solidity withdrawal function?
Blockchain / Solidity
function withdraw() public {
uint amount = balances[msg.sender];
require(amount > 0, "No balance");
(bool sent, ) = msg.sender.call{value: amount}("");
require(sent, "Failed to send Ether");
balances[msg.sender] = 0;
}Attempts:
2 left
💡 Hint
Consider what happens if the recipient is a contract with fallback code.
✗ Incorrect
Setting the balance to zero after sending ether allows a malicious contract to reenter the withdraw function before balance is cleared, draining funds.
📝 Syntax
advanced2:00remaining
Which option correctly implements a safe withdrawal pattern?
Choose the correct Solidity code snippet that safely implements the withdrawal pattern preventing reentrancy.
Attempts:
2 left
💡 Hint
Remember to update state before external calls and use recommended call syntax.
✗ Incorrect
Option A sets the balance to zero before calling external address, preventing reentrancy. It uses call with require to check success, which is the recommended pattern.
🚀 Application
expert3:00remaining
Calculate total withdrawn after multiple withdrawals
Given this contract snippet, what is the total ether withdrawn by
user after calling withdraw() twice, assuming deposit() was called once with 3 ether?Blockchain / Solidity
pragma solidity ^0.8.0; contract Withdrawal { mapping(address => uint) public balances; function deposit() public payable { balances[msg.sender] += msg.value; } function withdraw() public { uint amount = balances[msg.sender]; require(amount > 0, "No balance"); balances[msg.sender] = 0; (bool success, ) = msg.sender.call{value: amount}(""); require(success, "Transfer failed"); } }
Attempts:
2 left
💡 Hint
Consider the balance after the first withdrawal and what happens on the second call.
✗ Incorrect
After the first withdrawal, the balance is set to zero. The second withdrawal call fails the require check and reverts, so total withdrawn is 3 ether.