Bird
Raised Fist0
Blockchain / Solidityprogramming~10 mins

Multi-signature wallet concept in Blockchain / Solidity - Interactive Code Practice

Choose your learning style10 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Practice - 5 Tasks
Answer the questions below
1fill in blank
easy

Complete the code to define the minimum number of signatures required.

Blockchain / Solidity
uint constant MIN_SIGNATURES = [1];
Drag options to blanks, or click blank then click option'
A2
B4
C1
D3
Attempts:
3 left
💡 Hint
Common Mistakes
Setting the minimum signatures to 1 defeats the purpose of multi-signature.
Using a number higher than the total number of owners.
2fill in blank
medium

Complete the code to check if the number of collected signatures meets the minimum required.

Blockchain / Solidity
require(signaturesCount [1] MIN_SIGNATURES, "Not enough signatures");
Drag options to blanks, or click blank then click option'
A<
B>=
C!=
D==
Attempts:
3 left
💡 Hint
Common Mistakes
Using '<' would reject valid transactions.
Using '!=' would allow invalid counts.
3fill in blank
hard

Fix the error in the function that verifies if a signer is authorized.

Blockchain / Solidity
function isAuthorized(address signer) public view returns (bool) {
    return owners[[1]];
}
Drag options to blanks, or click blank then click option'
Asigner
Bmsg.sender
Caddress
Downer
Attempts:
3 left
💡 Hint
Common Mistakes
Using msg.sender instead of signer checks the wrong address.
Using 'address' or 'owner' are not valid variables here.
4fill in blank
hard

Fill both blanks to create a mapping that tracks signatures for each transaction.

Blockchain / Solidity
mapping(uint => mapping(address => [1])) public signatures;

function signTransaction(uint txId) public {
    signatures[txId][[2]] = true;
}
Drag options to blanks, or click blank then click option'
Abool
Bmsg.sender
Cuint
Daddress
Attempts:
3 left
💡 Hint
Common Mistakes
Using uint instead of bool for signature status.
Using address instead of msg.sender to mark the signer.
5fill in blank
hard

Fill all three blanks to create a function that executes a transaction after enough signatures.

Blockchain / Solidity
function executeTransaction(uint txId) public {
    require(signatures[txId][[1]], "Not signed by owner");
    require(signaturesCount [2] MIN_SIGNATURES, "Insufficient signatures");
    transactions[txId].[3]();
}
Drag options to blanks, or click blank then click option'
Amsg.sender
B>=
Ccall
Dtransfer
Attempts:
3 left
💡 Hint
Common Mistakes
Using transfer instead of call may not work for all transaction types.
Using '<' instead of '>=' causes logic errors.

Practice

(1/5)
1. What is the main purpose of a multi-signature wallet in blockchain?
easy
A. To require multiple approvals before spending funds
B. To speed up transaction processing
C. To store private keys on a single device
D. To allow unlimited spending by one user

Solution

  1. Step 1: Understand the multi-signature wallet concept

    A multi-signature wallet requires more than one person to approve a transaction before it can be executed.
  2. Step 2: Identify the main purpose

    This setup protects funds by preventing a single user from spending money alone, increasing security.
  3. Final Answer:

    To require multiple approvals before spending funds -> Option A
  4. Quick Check:

    Multi-signature = multiple approvals [OK]
Hint: Multi-signature means multiple people must approve [OK]
Common Mistakes:
  • Thinking it speeds up transactions
  • Believing one user controls all funds
  • Confusing it with single-key wallets
2. Which of the following is the correct way to define a multi-signature wallet threshold in Solidity?
easy
A. bool threshold = true;
B. uint8 threshold = '2';
C. string threshold = 2;
D. uint8 threshold = 1;

Solution

  1. Step 1: Identify correct data type for threshold

    The threshold is a number representing how many signatures are needed, so an unsigned integer like uint8 is appropriate.
  2. Step 2: Check syntax correctness

    Assigning a number directly to uint8 is correct. Using quotes or wrong types causes errors.
  3. Final Answer:

    uint8 threshold = 1; -> Option D
  4. Quick Check:

    Threshold is a number, use uint8 [OK]
Hint: Threshold is a number, use uint type without quotes [OK]
Common Mistakes:
  • Using quotes around numbers
  • Assigning string type to threshold
  • Using boolean type for threshold
3. Given this Solidity snippet for a multi-signature wallet, what will be the value of isApproved after calling approveTransaction(1, msg.sender) if the threshold is 2 and only one approval is made?
mapping(uint => mapping(address => bool)) approvals;
uint8 threshold = 2;

function approveTransaction(uint txId, address approver) public {
  approvals[txId][approver] = true;
}

function isApproved(uint txId) public view returns (bool) {
  uint count = 0;
  for (uint i = 0; i < owners.length; i++) {
    if (approvals[txId][owners[i]]) {
      count++;
    }
  }
  return count >= threshold;
}
medium
A. true
B. false
C. Compilation error
D. Undefined behavior

Solution

  1. Step 1: Understand approval counting logic

    The function counts how many owners approved the transaction and compares it to the threshold.
  2. Step 2: Analyze given scenario

    Only one approval is made but threshold is 2, so count is 1 which is less than 2.
  3. Final Answer:

    false -> Option B
  4. Quick Check:

    Approvals < threshold = false [OK]
Hint: Approval count must meet threshold to be true [OK]
Common Mistakes:
  • Assuming one approval is enough
  • Ignoring threshold comparison
  • Confusing approval mapping structure
4. Identify the bug in this Solidity function for approving transactions in a multi-signature wallet:
function approveTransaction(uint txId) public {
  approvals[txId][msg.sender] = true;
  if (isApproved(txId)) {
    executeTransaction(txId);
  }
}

function isApproved(uint txId) public view returns (bool) {
  uint count = 0;
  for (uint i = 0; i <= owners.length; i++) {
    if (approvals[txId][owners[i]]) {
      count++;
    }
  }
  return count >= threshold;
}
medium
A. Missing event emission after approval
B. approveTransaction should be external, not public
C. Loop condition should be < instead of <=
D. executeTransaction should not be called inside approveTransaction

Solution

  1. Step 1: Check the for loop boundary

    The loop uses i <= owners.length, which causes out-of-bounds access because array indices go from 0 to length-1.
  2. Step 2: Correct the loop condition

    Changing to i < owners.length prevents accessing invalid index and runtime errors.
  3. Final Answer:

    Loop condition should be < instead of <= -> Option C
  4. Quick Check:

    Array index out of bounds fixed by < [OK]
Hint: Array loops use < length, not <= length [OK]
Common Mistakes:
  • Using <= in loops causing errors
  • Ignoring array index limits
  • Thinking event emission fixes logic bugs
5. You want to create a multi-signature wallet that requires 3 out of 5 owners to approve a transaction. Which approach correctly enforces this rule in Solidity?
mapping(uint => mapping(address => bool)) approvals;
address[5] owners;
uint8 threshold = 3;

function executeTransaction(uint txId) public {
  uint count = 0;
  for (uint i = 0; i < owners.length; i++) {
    if (approvals[txId][owners[i]]) {
      count++;
    }
  }
  if (count >= threshold) {
    // execute the transaction
  } else {
    revert("Not enough approvals");
  }
}
hard
A. This code correctly enforces the 3-of-5 approval rule
B. The threshold should be set to 5 to require all owners
C. The loop should iterate over approvals, not owners
D. Revert should be replaced with a simple return statement

Solution

  1. Step 1: Analyze the approval counting logic

    The code counts how many owners approved the transaction by checking the approvals mapping for each owner.
  2. Step 2: Check threshold enforcement

    If the count is at least the threshold (3), the transaction executes; otherwise, it reverts with an error.
  3. Final Answer:

    This code correctly enforces the 3-of-5 approval rule -> Option A
  4. Quick Check:

    Count approvals >= threshold = enforce rule [OK]
Hint: Count approvals, compare with threshold, revert if not met [OK]
Common Mistakes:
  • Setting threshold incorrectly
  • Looping over wrong data structure
  • Using return instead of revert for errors