Lesson 06 · Security

Security & Key Management

Two ways a tokenized asset gets stolen: someone takes your keys, or someone breaks your code. An engineering leader has to defend, review, and hire against both.

Why this, now? You're accountable for what your team ships and who you trust to ship it. You don't need to write secure Solidity — you need to read an audit report without nodding along blankly, ask the question that exposes a weak design, and own the custody decision that protects the agent key (the one with freeze/mint/recover powers, Lesson 4). This lesson is the threat model behind every review you'll run.

The two attack surfaces

Frame everything in security around which surface is exposed. They fail differently and are defended differently.

① Keys (off-chain)

Whoever holds a private key is the account (Lesson 2). Steal the agent key → you can freeze, mint, force-transfer. No password reset, no chargeback. Defended by custody & key management.

② Code (on-chain)

A bug in the contract is exploitable by anyone, forever, and the loss is irreversible (immutability, Lesson 1). Defended by secure coding, audits, and upgrade paths.
Most catastrophic crypto losses are one of these two: a stolen key, or a flawed contract. When you review a design, ask of every component: "who holds the key here, and what code can move the asset?"

Surface ①: Key management & custody

The question is never "is the key safe?" but "how is signing authority split so no single failure is fatal?" Four points on a spectrum, weakest to strongest for an institution:1

ModelHow it worksWatch-out
Single keyOne private key signs. A laptop, a hardware wallet.Single point of failure. Never for institutional assets.
MultisigM-of-N independent keys must sign (e.g. 2-of-3). Policy enforced on-chain, publicly verifiable.Chain-specific; not all chains support it; changing signers needs a new wallet + on-chain tx.
MPCOne key split into shares; parties co-compute a signature without ever assembling the key. Cryptographic, chain-agnostic.Trust in the MPC implementation; off-chain (not publicly verifiable like multisig).
HSMKeys live in tamper-resistant hardware managed by a regulated custodian; you never hold them.Operational dependence on the custodian.

Where Fireblocks sits: MPC-CMP with key shares in hardware-isolated enclaves (TEEs) + a policy engine ("transfers > $1M need two approvers", "only whitelisted destinations").1 Real institutions go hybrid: MPC for hot operational accounts, multisig/HSM cold storage for reserves. The policy layer matters as much as the cryptography — most "hacks" are an authorised key used wrongly, not broken math.

Surface ②: Smart-contract failure modes

You don't need to find these — you need to recognise the names in an audit and know what they mean. The OWASP Smart Contract Top 10 (2025) is the canonical list; the four you must know:2

VulnerabilityThe essence
Access control (#1, >$950M in 2024)A privileged function (mint, freeze, upgrade) isn't properly restricted — anyone can call it. The single biggest loss category. Ask: "who can call each privileged function, and how is that enforced?"
ReentrancyA contract makes an external call before updating its own state, letting the callee re-enter and repeat the action (e.g. withdraw twice). Fixed by "checks-effects-interactions". The classic (The DAO, 2016).
Logic errorsThe code is "secure" but the business rules are wrong — a miscalculated fee, a broken cap, an off-by-one in eligibility. No tool catches these; only review and testing do.
Oracle manipulationFeeding the contract a false external value to exploit it (Lesson 1's oracle problem, weaponised). Ask: "what stops a bad/stale price from being acted on?"
// Reentrancy in one glance — the bug and the fix
// BAD: external call before state update
send(msg.sender, bal[msg.sender]);   // callee can re-enter here...
bal[msg.sender] = 0;                  // ...before this runs

// GOOD: checks-effects-interactions — update state FIRST
uint amt = bal[msg.sender];
bal[msg.sender] = 0;                  // effect
send(msg.sender, amt);                // interaction last

Upgradeability: the immutability dilemma

Lesson 1 said deployed code is immutable. But you'll need to fix bugs and change compliance rules. The industry's answer is the proxy pattern: a permanent proxy contract holds the data and address, and forwards calls to a swappable logic contract. Upgrade = point the proxy at new logic.

Buys youCosts you
Fix bugs, evolve rules, keep the same address & balancesA powerful upgrade key: whoever holds it can replace the logic — i.e. rewrite the rules of your asset
Upgradeability converts an immutability risk into a key risk (Surface ①). The hard question is governance: who can upgrade, behind what multisig/timelock? "Immutable but bug-stuck" vs "upgradeable but admin-trusted" is a genuine architectural trade-off you must be able to argue both sides of.

How to read an audit (practical)

The Marketnode lens & interview angles

Retrieve it (don't peek)

From memory. Interleaves Lessons 1, 2 & 4.

1. What does the MPC custody model actually do with the private key?
2. According to OWASP, which smart-contract flaw causes the largest real-world losses?
3. Making a contract upgradeable via a proxy mainly converts one kind of risk into another. Into what?

Primary source

Two authoritative reads for your two surfaces: OWASP Smart Contract Top 10 (the vulnerability vocabulary every audit uses) and Fireblocks — MPC vs Multi-Sig (the custody trade-off, from the market leader). For depth on secure patterns, the OpenZeppelin Contracts docs are the de-facto standard library your team will use.

I'm your teacher — ask me. Want me to build a security design-review checklist tailored to an ERC-3643 deployment, or a set of security interview questions with model answers for hiring? Or walk a real audit report's structure? Just ask.