30 Security Mistakes DeFi Developers Make
DeFi protocols are high-value targets. These common mistakes have led to billions in losses. Learn from others' failures to build more secure protocols.
Oracle Mistakes
Price oracle vulnerabilities that lead to manipulation.
Using spot prices from DEXes
Using instantaneous spot prices from AMMs allows flash loan manipulation to move prices within a single transaction.
What happens: Attackers drain funds through price manipulation
Fix: Use Chainlink or TWAP oracles. Never rely on single-block spot prices.
No staleness check on oracle data
Using stale oracle prices when Chainlink hasn't updated in hours or days.
What happens: Incorrect prices lead to bad liquidations or arbitrage
Fix: Check updatedAt timestamp. Reject prices older than acceptable threshold.
Missing oracle fallback
Protocol breaks completely when primary oracle fails or returns zero.
What happens: Protocol freeze or incorrect behavior during oracle downtime
Fix: Implement fallback oracles or safe failure modes.
Ignoring oracle decimal differences
Assuming all Chainlink feeds have 8 decimals when some have different precision.
What happens: Orders of magnitude errors in price calculations
Fix: Always check feed decimals and normalize to consistent precision.
Single oracle dependency
Trusting one oracle source without cross-validation for critical operations.
What happens: Oracle compromise breaks entire protocol
Fix: For critical operations, cross-reference multiple oracle sources.
Flash Loan Mistakes
Vulnerabilities exploitable through flash loans.
Governance votes based on current balance
Allowing votes based on token balance at time of vote enables flash loan governance attacks.
What happens: Attacker passes malicious proposals with borrowed voting power
Fix: Use snapshot voting. Require tokens held for minimum time before voting.
Rewards based on deposit amount without time lock
Distributing rewards proportional to deposits without lockup allows flash loan reward stealing.
What happens: Attackers claim disproportionate share of rewards
Fix: Require deposits to be present for multiple blocks before earning rewards.
Share price manipulation on first deposit
First depositor can donate tokens to inflate share price, griefing subsequent depositors.
What happens: Early depositors extract value from later depositors
Fix: Implement virtual shares or send initial deposit to dead address.
Collateral value from manipulable source
Using AMM liquidity token value based on reserves allows collateral manipulation.
What happens: Attackers borrow more than collateral is worth
Fix: Use manipulation-resistant LP token pricing or don't accept LP as collateral.
Liquidation triggers based on spot price
Liquidation decisions using spot prices allow predatory liquidations via price manipulation.
What happens: Healthy positions liquidated through temporary price manipulation
Fix: Use TWAP for liquidation triggers. Add liquidation delay.
Reentrancy Mistakes
Various forms of reentrancy vulnerabilities.
State updates after external calls
Updating balances or state after making external calls violates checks-effects-interactions.
What happens: Attacker re-enters and exploits stale state
Fix: Always update state before external calls. Use ReentrancyGuard.
Missing reentrancy guard on withdraw
Withdraw functions making ETH transfers without reentrancy protection.
What happens: Classic reentrancy drain attack
Fix: Add ReentrancyGuard modifier to all functions with external calls.
Cross-contract reentrancy blind spots
Only checking single contract reentrancy when protocol has multiple contracts sharing state.
What happens: Attacker re-enters through different contract in same protocol
Fix: Use global reentrancy lock across all protocol contracts.
ERC-777 callback reentrancy
Accepting any ERC-20 without considering ERC-777 tokens have transfer hooks.
What happens: Reentrancy through token transfer callbacks
Fix: Use ReentrancyGuard or whitelist accepted tokens.
Read-only reentrancy in view functions
View functions returning stale data when called during reentrancy.
What happens: External protocols that read state during attack get wrong values
Fix: Be aware of what external protocols might read. Document reentrancy behavior.
Math and Logic Mistakes
Calculation errors and business logic flaws.
Division before multiplication
Order of operations causing precision loss. Dividing before multiplying loses precision.
What happens: Small amounts round to zero, value leakage over time
Fix: Always multiply before divide. Use higher precision intermediates.
Rounding always favoring users
Rounding in a direction that allows users to extract dust amounts repeatedly.
What happens: Slow drain through rounding exploitation
Fix: Round in favor of the protocol for withdrawals, in favor of users for deposits.
Unchecked array operations
Loops over unbounded arrays that can grow beyond gas limits.
What happens: Function becomes uncallable, funds stuck
Fix: Bound array sizes or use pagination for large datasets.
Integer overflow in fee calculations
Fee percentage times amount overflowing before division.
What happens: Wrong fees charged or underflow to huge values
Fix: Check for overflow even with Solidity 0.8. Use unchecked carefully.
Missing slippage protection
Swaps without minimum output parameter allowing sandwich attacks.
What happens: Users receive much less than expected due to MEV
Fix: Always include minAmountOut parameter. Let users set slippage tolerance.
Incorrect share calculations
Vault share math that allows rounding exploitation or share inflation.
What happens: Value extraction through share manipulation
Fix: Use battle-tested ERC-4626 implementations. Add first depositor protection.
Token Handling Mistakes
Errors in handling various token types.
Assuming all ERC-20s return bool
Not using SafeERC20 when some tokens (USDT) don't return bool on transfer.
What happens: Transfers silently fail or revert unexpectedly
Fix: Always use SafeERC20 for ERC-20 interactions.
Not handling fee-on-transfer tokens
Assuming received amount equals transfer amount for tokens with transfer fees.
What happens: Accounting errors, potential for exploitation
Fix: Calculate actual received amount via balance difference.
Ignoring token decimals
Assuming 18 decimals when USDC has 6 and others vary.
What happens: Off by orders of magnitude in calculations
Fix: Query token decimals. Normalize all calculations.
Approval race condition
Approving new amount without resetting to zero first for tokens with approval race condition.
What happens: Approved party can spend old + new allowance
Fix: Reset to zero first or use increaseAllowance/decreaseAllowance.
Not considering token blocklists
Ignoring that USDC/USDT can blocklist addresses, breaking protocol flows.
What happens: Funds stuck if protocol address gets blocklisted
Fix: Have contingency for blocklist scenarios. Avoid holding stablecoins long-term.
Access Control Mistakes
Permission and authorization vulnerabilities.
Missing access control on critical functions
Administrative functions without onlyOwner or role checks.
What happens: Anyone can call admin functions and drain or break protocol
Fix: Audit every external/public function. Default to restricted, explicitly open.
Single key controlling everything
One EOA can pause, upgrade, and withdraw all funds.
What happens: Key compromise loses everything
Fix: Use multisig for admin functions. Separate roles for different operations.
No timelock on critical operations
Upgrades and parameter changes execute immediately without delay.
What happens: No time for users to react to malicious changes
Fix: Add timelock for all critical admin operations.
Incorrect modifier ordering
Putting access control modifier after other checks allows bypass in some cases.
What happens: Access control bypassed via early revert
Fix: Access control modifiers should be first in modifier chain.
Tips from the field
- 1.
Study every DeFi exploit post-mortem. The patterns repeat with variations.
- 2.
Get multiple audits from different firms. Each auditor catches different issues.
- 3.
Deploy with low caps first. Increase limits gradually as protocol proves secure.
- 4.
Have a bug bounty program. Ethical hackers finding bugs is better than malicious ones.
- 5.
Build monitoring and alerts from day one. Fast response limits damage.