Bird
Raised Fist0
Blockchain / Solidityprogramming~10 mins

Reentrancy guard pattern in Blockchain / Solidity - Interactive Code Practice

Choose your learning style10 modes available
Practice - 5 Tasks
Answer the questions below
1fill in blank
easy

Complete the code to declare a boolean variable named 'locked' initialized to false.

Blockchain / Solidity
bool [1] = false;
Drag options to blanks, or click blank then click option'
AisLocked
Block
Cstatus
Dlocked
Attempts:
3 left
💡 Hint
Common Mistakes
Using a different variable name like 'lock' or 'status' which is not standard.
2fill in blank
medium

Complete the modifier to check if the contract is not locked before running the function.

Blockchain / Solidity
modifier noReentrant() {
    require(![1], "Reentrant call");
    _;
}
Drag options to blanks, or click blank then click option'
Alocked
BisLocked
Clock
Dstatus
Attempts:
3 left
💡 Hint
Common Mistakes
Checking the wrong variable or missing the negation operator.
3fill in blank
hard

Fix the error in the modifier to set the locked state correctly before and after the function runs.

Blockchain / Solidity
modifier noReentrant() {
    require(!locked, "Reentrant call");
    locked = [1];
    _;
    locked = false;
}
Drag options to blanks, or click blank then click option'
Atrue
Bstatus
Clocked
Dfalse
Attempts:
3 left
💡 Hint
Common Mistakes
Setting locked to false before the function runs, which disables the guard.
4fill in blank
hard

Fill both blanks to complete the safe withdraw function using the noReentrant modifier and resetting the locked state.

Blockchain / Solidity
function withdraw(uint amount) public noReentrant {
    require(balances[msg.sender] >= amount, "Insufficient balance");
    balances[msg.sender] -= amount;
    (bool success, ) = msg.sender.call{value: amount}([1]);
    require(success, "Transfer failed");
    locked = [2];
}
Drag options to blanks, or click blank then click option'
Agas(2300)
Bfalse
Ctrue
Dgas()
Attempts:
3 left
💡 Hint
Common Mistakes
Using gas(2300) which limits gas and can cause failures.
Not resetting locked to false.
5fill in blank
hard

Fill all three blanks to create a dictionary comprehension that maps addresses to their balances only if balance is greater than zero.

Blockchain / Solidity
mapping(address => uint) public balances;

function positiveBalances(address[] memory users) public view returns (mapping(address => uint) memory) {
    return {user: balances[user] for user in users if balances[user] [1] 0};
}

modifier noReentrant() {
    require(!locked, "Reentrant call");
    locked = [2];
    _;
    locked = [3];
}
Drag options to blanks, or click blank then click option'
A>
Btrue
Cfalse
D<
Attempts:
3 left
💡 Hint
Common Mistakes
Using < or wrong boolean values in the modifier.

Practice

(1/5)
1.

What is the main purpose of the reentrancy guard pattern in blockchain smart contracts?

easy
A. To prevent a function from being called again before it finishes execution
B. To speed up the execution of smart contracts
C. To allow multiple users to access a function simultaneously
D. To reduce the gas cost of transactions

Solution

  1. Step 1: Understand the problem reentrancy causes

    Reentrancy happens when a function is called again before the first call finishes, causing unexpected behavior or exploits.
  2. Step 2: Identify the role of the reentrancy guard

    The reentrancy guard uses a lock to block repeated calls until the first call completes, preventing reentrancy attacks.
  3. Final Answer:

    To prevent a function from being called again before it finishes execution -> Option A
  4. Quick Check:

    Reentrancy guard = prevent repeated calls [OK]
Hint: Reentrancy guard stops repeated calls during execution [OK]
Common Mistakes:
  • Thinking it speeds up contract execution
  • Believing it allows simultaneous access
  • Confusing it with gas optimization
2.

Which of the following is the correct way to declare a reentrancy guard variable in Solidity?

contract Example {
    // Fill in the blank
    _____ private locked = false;
}
easy
A. string
B. bool
C. int
D. address

Solution

  1. Step 1: Identify the variable type for a lock

    The lock variable is used as a flag to indicate if the function is running, so it should be a boolean (true/false).
  2. Step 2: Match the correct Solidity type

    In Solidity, bool is the type for true/false values, suitable for a lock variable.
  3. Final Answer:

    bool -> Option B
  4. Quick Check:

    Lock variable type = bool [OK]
Hint: Lock variables are boolean flags in Solidity [OK]
Common Mistakes:
  • Using int instead of bool for lock
  • Using string or address types incorrectly
  • Forgetting to initialize the variable
3.

Consider this Solidity function using a reentrancy guard:

bool private locked = false;

function withdraw(uint amount) public {
    require(!locked, "Reentrant call detected");
    locked = true;
    (bool success, ) = msg.sender.call{value: amount}("");
    require(success, "Transfer failed");
    locked = false;
}

What happens if msg.sender.call triggers a fallback that calls withdraw again?

medium
A. The second call is blocked by the lock and reverts
B. The second call succeeds and causes reentrancy
C. The contract runs out of gas and fails
D. The lock variable resets before the second call

Solution

  1. Step 1: Analyze the lock status during the first call

    When withdraw is called, locked is set to true before sending funds.
  2. Step 2: Understand the effect on reentrant call

    If msg.sender.call triggers a fallback that calls withdraw again, the require(!locked) check fails because locked is true, blocking the call.
  3. Final Answer:

    The second call is blocked by the lock and reverts -> Option A
  4. Quick Check:

    Lock true blocks reentrant call [OK]
Hint: Lock true means no reentrant calls allowed [OK]
Common Mistakes:
  • Assuming reentrancy still happens
  • Thinking lock resets before second call
  • Confusing gas failure with reentrancy
4.

Identify the bug in this reentrancy guard implementation:

bool private locked = false;

function withdraw(uint amount) public {
    require(!locked, "Reentrant call detected");
    (bool success, ) = msg.sender.call{value: amount}("");
    require(success, "Transfer failed");
    locked = true;
    locked = false;
}
medium
A. The require statement is missing
B. The lock variable is never set to true
C. The lock is set after the external call, allowing reentrancy
D. The call to msg.sender is incorrect syntax

Solution

  1. Step 1: Check when the lock is set

    The lock is set to true only after the external call, which means the function is not protected during the call.
  2. Step 2: Understand reentrancy risk

    Because the lock is set too late, a reentrant call can happen during the external call, causing vulnerability.
  3. Final Answer:

    The lock is set after the external call, allowing reentrancy -> Option C
  4. Quick Check:

    Lock must be set before external calls [OK]
Hint: Set lock before external calls to prevent reentrancy [OK]
Common Mistakes:
  • Setting lock after external call
  • Forgetting to set lock at all
  • Misplacing require statements
5.

You want to protect a function that updates user balances and sends Ether. Which is the best way to apply the reentrancy guard pattern?

function safeWithdraw(uint amount) public {
    // Your code here
    balances[msg.sender] -= amount;
    (bool success, ) = msg.sender.call{value: amount}("");
    require(success, "Transfer failed");
}
hard
A. Update balances after sending Ether without any lock
B. Do not use any lock, just rely on require statements
C. Use a lock variable but set it after sending Ether
D. Set a lock variable before updating balances and sending Ether, then release it after

Solution

  1. Step 1: Understand the order of operations for safety

    To prevent reentrancy, set a lock before any state changes and external calls, then release it after.
  2. Step 2: Apply the reentrancy guard pattern correctly

    Set the lock variable to true before updating balances and sending Ether, then set it back to false after the transfer completes.
  3. Final Answer:

    Set a lock variable before updating balances and sending Ether, then release it after -> Option D
  4. Quick Check:

    Lock before state change and external call [OK]
Hint: Lock before balance update and transfer, unlock after [OK]
Common Mistakes:
  • Setting lock after sending Ether
  • Updating balances after external call
  • Not using any lock at all
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