By Fatskills Exam Guides Team — the exam nerds behind 28,500+ quizzes and 2.1M practice questions across 500+ global exams.
A Central Bank Digital Currency (CBDC) is a sovereign‑issued digital token that represents a nation’s fiat money on a blockchain‑like ledger. When paired with tokenized assets—real‑world securities, commodities, or property wrapped as ERC‑20/721 tokens—it lets traditional finance interact with decentralized protocols (e.g., a user swaps a tokenized US‑treasury for a CBDC on a DEX, or a DAO votes on how to allocate a tokenized real‑estate fund). The combination promises instant settlement, programmable money, and global access while preserving central‑bank control.
solidity contract TokenizedBond is ERC20 { constructor() ERC20("TokenizedBond", "TBOND") { _mint(msg.sender, 1_000_000 * 10decimals()); } }
solidity contract PropertyDeed is ERC721 { constructor() ERC721("PropertyDeed", "PD") {} function mint(address to, uint256 tokenId) external { _safeMint(to, tokenId); } }
solidity // Simplified bridge lock function function lock(uint256 amount) external { require(cbdcToken.transferFrom(msg.sender, address(this), amount)); emit Locked(msg.sender, amount); }
solidity // HTLC skeleton function claim(bytes32 preimage) external { require(keccak256(abi.encodePacked(preimage)) == hashLock); // release locked tokens }
solidity function transfer(address to, uint256 amount) external { require(isApprovedMerchant(to), "Blocked merchant"); _transfer(msg.sender, to, amount); }
solidity interface IRegOracle { function isCompliant(address) external view returns (bool); }
bash npx hardhat compile npx hardhat run scripts/deployBridge.js --network goerli
isCompliant
mint
unlock
lock
claim
javascript const bridge = new ethers.Contract(bridgeAddr, bridgeAbi, signer); await bridge.lock(ethers.utils.parseUnits("1000", 18));
Mistake: Using tx.origin for access control (e.g., require(tx.origin == owner)). Correction: Use msg.sender and role‑based modifiers (onlyOwner). tx.origin can be spoofed through a malicious contract, breaking security.
tx.origin
require(tx.origin == owner)
msg.sender
onlyOwner
Mistake: Forgetting to pause the bridge contract during upgrades. Correction: Implement OpenZeppelin’s Pausable and call pause() before any state‑changing migration. This prevents funds from being locked while the code is inconsistent.
Pausable
pause()
Mistake: Assuming the ERC‑20 bridge token is “real” CBDC and skipping KYC checks. Correction: Wire the regulatory oracle into every mint/transfer path; otherwise the token can be used for illicit transfers, violating central‑bank policy.
transfer
Mistake: Hard‑coding the bridge’s destination chain ID, making future cross‑chain extensions impossible. Correction: Store the target chain ID in a mutable uint256 public targetChainId; and expose a setter only callable by governance.
uint256 public targetChainId;
Mistake: Not handling re‑entrancy when the bridge calls an external oracle. Correction: Follow the Checks‑Effects‑Interactions pattern or use nonReentrant from OpenZeppelin.
nonReentrant
“Explain the difference between call and delegatecall in the context of a CBDC bridge.” *Interviewers expect you to note that call executes code in the callee’s context (its storage), while delegatecall runs the callee’s code against the caller’s storage—critical when a proxy bridge forwards logic to an upgradeable implementation.
call
delegatecall
“Why would a regulator prefer a permissioned ledger for CBDC issuance but allow ERC‑20 wrappers on a public chain?” *The answer should mention sovereign control, auditability, and privacy on the permissioned side, plus liquidity and composability benefits on the public side.
“What are the gas‑cost trade‑offs between using ERC‑20 vs. ERC‑777 for tokenized assets?” *ERC‑777 adds hooks (tokensReceived) that increase bytecode size and gas, but it enables safer interactions (e.g., preventing accidental token loss).
tokensReceived
“How does an HTLC guarantee atomicity across a permissioned CBDC chain and Ethereum?” *Explain the hash lock, time lock, and the need for both parties to reveal the same preimage within the timeout, ensuring either both sides complete or both revert.
Scenario: A bridge contract uses require(msg.sender == owner) to restrict minting, but the owner address is stored in a public variable that can be overwritten. Answer: This is unsafe because anyone can call a function that changes owner (e.g., via a governance upgrade) and then mint unlimited tokens. Use OpenZeppelin’s Ownable with immutable ownership or a multi‑sig DAO guard.
require(msg.sender == owner)
owner
Ownable
Scenario: A tokenized‑asset ERC‑721 contract allows transferFrom without checking isCompliant from the regulatory oracle. Answer: The asset can be moved to non‑KYC‑verified wallets, violating AML rules. Add a require(oracle.isCompliant(to)) guard in _beforeTokenTransfer.
transferFrom
require(oracle.isCompliant(to))
_beforeTokenTransfer
Scenario: A developer writes an HTLC that only checks the hash lock but forgets the timeout. Answer: The contract could be locked forever if the counter‑party never reveals the preimage. Always include a require(block.timestamp < expiry) revert path.
require(block.timestamp < expiry)
unchecked {}
i++
view
bool
Join 4M+ learners. Unlock unlimited quizzes, wrong-answer tracking, flashcards + reminders, study guides, and 1-on-1 challenges.