0
0
Blockchain / Solidityprogramming~20 mins

Withdrawal patterns in Blockchain / Solidity - Practice Problems & Coding Challenges

Choose your learning style9 modes available
Challenge - 5 Problems
🎖️
Withdrawal Pattern Master
Get all challenges correct to earn this badge!
Test your skills under time pressure!
Predict Output
intermediate
2: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;
    }
}
AThe contract runs out of gas and reverts
BThe contract throws an error because balances[msg.sender] is not updated before transfer
CThe user balance remains 5 ether after withdrawal
DThe user receives 5 ether and their balance resets to 0
Attempts:
2 left
💡 Hint
Think about the order of state update and transfer in the withdrawal function.
🧠 Conceptual
intermediate
1: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?
AIt prevents reentrancy attacks by letting users withdraw funds themselves
BIt reduces gas costs by batching transfers automatically
CIt allows contracts to send ether to multiple users simultaneously
DIt guarantees instant transfer of ether without delays
Attempts:
2 left
💡 Hint
Think about security risks when sending ether directly.
🔧 Debug
advanced
2: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;
}
AThe call method is deprecated and should use transfer instead
BThe balance is set to zero after sending ether, risking reentrancy attack
CThe function does not check if msg.sender is a contract
DThe require statement should be after setting balance to zero
Attempts:
2 left
💡 Hint
Consider what happens if the recipient is a contract with fallback code.
📝 Syntax
advanced
2:00remaining
Which option correctly implements a safe withdrawal pattern?
Choose the correct Solidity code snippet that safely implements the withdrawal pattern preventing reentrancy.
A
function withdraw() public {
    uint amount = balances[msg.sender];
    require(amount > 0);
    balances[msg.sender] = 0;
    (bool success, ) = msg.sender.call{value: amount}("");
    require(success);
}
B
function withdraw() public {
    uint amount = balances[msg.sender];
    require(amount > 0);
    (bool success, ) = msg.sender.call{value: amount}("");
    require(success);
    balances[msg.sender] = 0;
}
C
function withdraw() public {
    uint amount = balances[msg.sender];
    balances[msg.sender] = 0;
    (bool success, ) = msg.sender.transfer(amount);
    require(success);
}
D
function withdraw() public {
    uint amount = balances[msg.sender];
    require(amount > 0);
    balances[msg.sender] = 0;
    msg.sender.transfer(amount);
}
Attempts:
2 left
💡 Hint
Remember to update state before external calls and use recommended call syntax.
🚀 Application
expert
3: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");
    }
}
A0 ether
B6 ether
C3 ether
DReverts on second withdrawal
Attempts:
2 left
💡 Hint
Consider the balance after the first withdrawal and what happens on the second call.