CBSA Smart Contract Design 3 — Questions and Answers
Question 1: Which Solidity visibility modifier should be used for functions that are only intended to be called internally and not inherited by child contracts?
- public
- external
- internal
- private (Correct answer)
Correct answer: private
The 'private' modifier restricts a function to the defining contract only, excluding derived contracts, unlike 'internal' which is accessible in child contracts.
Question 2: What is the main advantage of using 'events' in smart contracts over storing data in contract state?
- Events are cheaper to emit than writing to storage and can be indexed for efficient off-chain querying (Correct answer)
- Events permanently alter the blockchain state just like storage variables
- Events allow smart contracts to call external APIs directly
- Events prevent other contracts from reading sensitive data
Correct answer: Events are cheaper to emit than writing to storage and can be indexed for efficient off-chain querying
Emitting events costs significantly less gas than writing to storage, and indexed event parameters enable efficient filtering by off-chain applications.
Question 3: In a multi-signature smart contract wallet requiring M-of-N approvals, what data structure is most appropriate for tracking which owners have signed a pending transaction?
- A mapping from owner address to boolean (Correct answer)
- An array of transaction hashes
- A single uint256 counter
- A linked list of pending approvals
Correct answer: A mapping from owner address to boolean
A mapping(address => bool) provides O(1) lookup to check if a specific owner has already signed, preventing duplicate approvals efficiently.
Question 4: What does 'ABI encoding' refer to in the context of smart contract interaction?
- The encryption of contract bytecode before deployment
- The standardized encoding of function calls and return values for EVM interoperability (Correct answer)
- The compression of contract state to reduce storage costs
- The hashing of contract addresses to generate unique identifiers
Correct answer: The standardized encoding of function calls and return values for EVM interoperability
ABI (Application Binary Interface) encoding defines how function signatures and parameters are serialized into bytes for EVM calls and how return data is decoded.
Question 5: Which anti-pattern describes a smart contract that performs too many operations in a single transaction, risking hitting the block gas limit?
- Reentrancy loop
- Gas griefing through unbounded iteration (Correct answer)
- Timestamp dependence
- Integer underflow
Correct answer: Gas griefing through unbounded iteration
Iterating over an unbounded array or mapping in one transaction can exceed the block gas limit, causing the transaction to fail and potentially locking contract functionality.
Question 6: What is the role of a 'nonce' in smart contract design, particularly in meta-transaction or permit patterns?
- It measures the computational complexity of a transaction
- It prevents replay attacks by ensuring each signed message can only be used once (Correct answer)
- It determines the gas price for off-chain relayed transactions
- It identifies the block number in which a transaction was included
Correct answer: It prevents replay attacks by ensuring each signed message can only be used once
A nonce that increments with each use ensures a previously valid signature cannot be resubmitted to execute the same action multiple times.
Question 7: When designing a smart contract auction, why is a 'pull payment' pattern preferred over 'push payment' for refunding losing bidders?
- Pull payments allow the contract to earn interest on held funds
- Push payments fail if a recipient contract reverts, potentially blocking the entire auction (Correct answer)
- Pull payments automatically convert Ether to ERC-20 tokens
- Push payments are not supported in Solidity after version 0.8
Correct answer: Push payments fail if a recipient contract reverts, potentially blocking the entire auction
If a malicious bidder's fallback function reverts or a recipient is a contract that rejects Ether, a push-based refund loop would halt the entire auction contract.
Which Solidity visibility modifier should be used for functions that are only intended to be called internally and not inherited by child contracts?