Contract 1: Bank Withdrawal System
Correct Answer: The contract is vulnerable to reentrancy because it sends ETH to the caller before updating the balance. The vulnerable pattern is: check → external call → state update (should be: check → state update → external call).
- Full credit: Identifies reentrancy, explains external call before state update
- Partial credit (4 pts): Identifies reentrancy but vague explanation
- Partial credit (2 pts): Notes "security issue" without specificity
- No credit: Incorrect vulnerability or no answer
- Setup: Attacker deploys malicious contract with fallback/receive function that calls withdraw()
- Initial Deposit: Attacker deposits 1 ETH into Bank contract
- First Withdrawal: Attacker calls withdraw(1 ETH)
- Balance Check Passes: Contract verifies attacker has 1 ETH (✓ passes)
- ETH Sent: Contract sends 1 ETH to attacker, triggering malicious fallback
- Reentrant Call: Fallback function calls withdraw(1 ETH) again
- Balance Still 1 ETH: Balance hasn't been updated yet, check passes again
- Loop Continues: Attacker withdraws repeatedly until Bank is drained
- Final State Update: Original balance update executes (too late)
Example Code:
- Full credit: Step-by-step attack with fallback function explanation
- 7-6 pts: Clear steps but missing technical details (e.g., fallback mechanism)
- 5-4 pts: General idea but vague ("attacker steals funds repeatedly")
- 3-0 pts: Incorrect attack vector or minimal effort
Justification: Allows complete drainage of all contract funds with minimal setup. Historical precedent: The DAO hack (2016) exploited identical vulnerability for $60M loss.
- Full credit: Correct fix with explanation (any valid solution)
- 4 pts: Partially correct (e.g., mentions state update but no code)
- 2 pts: Wrong approach but shows understanding
| Estimated TVL at Risk: | $50,000,000 |
| Severity Factor (CRITICAL): | 1.0 |
| Base Bounty (TVL × Factor × 10%): | $5,000,000 |
| Typical Actual Payout: | $500,000 - $2,000,000 |
Note: Most protocols cap bounties at $500K-$1M even for critical issues. Immunefi reports median critical bounty is $500K.
- Full credit: Reasonable calculation using formula ($1M-$5M range)
- 2 pts: Uses formula but incorrect math
- 1 pt: Random guess without calculation
- Confusing reentrancy with overflow/underflow
- Not explaining the fallback function mechanism
- Suggesting "use transfer() instead" (not foolproof, limits gas)
- Claiming LOW severity (completely missing criticality)
Contract 2: Token Ownership Manager
Correct Answer: The setOwner() function lacks access control checks.
Anyone can call it and become the owner, gaining unlimited minting privileges and control over the protocol.
- Discovery: Attacker reads contract code, sees unprotected setOwner()
- Ownership Takeover: Attacker calls setOwner(attackerAddress)
- Verification: Attacker is now owner, original owner lost control
- Exploitation Options:
- Mint unlimited tokens to themselves
- Pause all transfers, locking user funds
- Set ownership to 0x0, permanently bricking the contract
- Mint tokens and sell on market, crashing price
- Impact: Complete protocol takeover, total loss of user trust and value
Justification: Complete protocol compromise. Attacker gains god-mode privileges. Historical precedent: Multiple DeFi protocols lost millions to access control bugs (Poly Network, Cream Finance).
| Estimated TVL at Risk: | $20,000,000 |
| Severity Factor (CRITICAL): | 1.0 |
| Estimated Bug Bounty: | $2,000,000 (capped at $500K-$1M typically) |
Contract 3: Simple Token Transfer
Correct Answer: The transfer function lacks balance validation before subtraction. If a user with 0 tokens transfers 1 token, underflow wraps to maximum uint256 value, creating tokens from nothing.
Note: This vulnerability only exists in Solidity versions prior to 0.8.0. In 0.8.0+, this would revert automatically.
- Full credit: Identifies integer underflow with explanation
- 4 pts: Identifies "missing balance check" without underflow concept
- 2 pts: Vague "can transfer more than they have"
- Setup: Attacker creates new account with 0 token balance
- Underflow Trigger: Attacker calls transfer(victimAddress, 1)
- Math Underflow: 0 - 1 wraps around to 2^256 - 1 (max uint256)
- God Mode: Attacker now has ~115 quattuorvigintillion tokens
- Exploitation: Attacker can:
- Transfer unlimited tokens to other accounts
- Dump tokens on DEX, draining all liquidity
- Manipulate governance (if tokens grant voting power)
- Destroy token economics and price
- Full credit: Explains underflow math (0 - 1 = max value)
- 6 pts: Explains exploitation without underflow math
- 4 pts: "Can get infinite tokens" without mechanism
Justification: Allows creation of unlimited tokens, destroying token economics. Not CRITICAL because it doesn't directly drain ETH, but still catastrophic. Historical example: BEC token (2018) had similar vulnerability, value went to zero.
| Estimated TVL at Risk: | $30,000,000 |
| Severity Factor (HIGH): | 0.5 |
| Estimated Bug Bounty: | $1,500,000 (capped at $250K-$750K typically) |
Comparative Analysis Answers
Accept Either:
- Contract 1 (Reentrancy): Most severe because it allows immediate, complete fund drainage with simple setup. The DAO hack demonstrated this can extract tens of millions in minutes.
- Contract 2 (Access Control): Most severe because it grants god-mode control, allowing attacker to mint unlimited tokens, pause contracts, and permanently brick the protocol.
Key Point: Both are CRITICAL. The "most severe" depends on context - reentrancy for immediate fund loss, access control for permanent protocol compromise.
- Full credit: Chooses Contract 1 or 2 with solid justification
- 3 pts: Correct choice but weak reasoning
- 0 pts: Chooses Contract 3 (clearly less severe than others)
Possible Connections:
- All Three Share: State management issues - improper ordering of checks, effects, and interactions
- Contracts 1 & 3: Both involve arithmetic on balances without proper validation
- Compound Scenario: If Contract 2's attacker gains control, they could exploit Contracts 1 or 3 more easily (e.g., mint tokens to themselves before underflow attack)
- Pattern: All stem from insufficient input validation and state protection
| Scenario | Potential Profit | Risk/Consequences |
|---|---|---|
| Exploit | $10M-$50M (protocol TVL) |
• Federal prosecution (wire fraud, computer fraud) • 10-20 year prison sentence • Funds frozen/seized by authorities • Chain analysis tracks laundering • Lifetime reputation destruction |
| Report (Bug Bounty) | $500K-$2M bounty |
• Zero legal risk • Career enhancement • Reputation as ethical hacker • Future employment opportunities • Community respect |
| Rational Choice |
REPORT via bug bounty
Reasoning: Expected value calculation: • Exploit: $25M × 10% chance of success × 50% laundering success = $1.25M • Report: $1M × 100% chance = $1M When factoring in 90% chance of prison (negative $1M+ value), exploitation EV is deeply negative. Reporting is strictly dominant strategy. |
|
Additional Factors:
- Mechanism Design Success: Bug bounties align incentives, making reporting more profitable than attacking (when accounting for risk)
- Social Capital: Reputation in crypto is worth millions in future opportunities
- Moral Hazard: Existence of bounties reduces attacks by ~70% (industry estimates)
- Full credit: Quantitative comparison with rational choice explanation
- 6 pts: Qualitative comparison with correct conclusion
- 4 pts: Lists pros/cons without conclusion
- 0 pts: Concludes exploitation is rational (misses key risks)
Key Takeaways:
- Incentive Alignment: Bug bounties create game where reporting beats exploiting
- Security as Economics: Code correctness alone insufficient; must incentivize security behavior
- Adversarial Assumptions: Must design assuming rational attackers constantly probing for exploits
- Defense in Depth: Multiple layers needed - code audits, bounties, formal verification, time-locks
- Transparency Trade-off: Open-source code enables both security research and attacker reconnaissance
- Time Value: Attackers move faster than auditors; bounties provide 24/7 security
- MEV Considerations: Some vulnerabilities only exploitable with specific on-chain conditions, adding complexity
- Full credit: 3+ valid insights about mechanism design
- 3 pts: 1-2 insights
- 1 pt: Generic "security is important" statement
Bonus Contracts - Brief Answers
Vulnerability: The withdraw function calculates user's share based on current pool balance, which can be manipulated with flash loans. Attacker can deposit, take flash loan to artificially inflate balance, withdraw larger share, then repay loan.
Fix: Track deposits separately from total balance, use share-based accounting that's immune to balance manipulation.
Vulnerability: Uses spot prices from DEX pools, which can be manipulated in single transaction. Attacker can skew pool ratios with large trades, get inflated price from oracle, borrow maximum, then restore pool ratio.
Fix: Use time-weighted average prices (TWAP), multiple independent oracles, or Chainlink price feeds.
Vulnerabilities:
- Timestamp Dependence: Miners can manipulate block.timestamp within ~15 seconds
- Lock Extension Bug: extendLock resets unlock time from current block.timestamp, allowing users to lock funds indefinitely or reduce lock time by calling repeatedly
Fix: For extendLock, should be: unlockTime[msg.sender] += additionalTime
(add to existing, not reset from now)
- Each bonus contract: +3.33 points for correct vulnerability identification and fix
- Partial credit available for partially correct answers
© Joerg Osterrieder 2025-2026. All rights reserved.