DeFi Security Patterns
Decentralized Finance Security
DeFi protocols face unique security challenges due to their composability, financial nature, and complex tokenomics. This guide focuses on security patterns specific to DeFi projects.
Economic Security Design
Incentive Alignment
- Ensure economic incentives align with desired protocol behavior
- Model incentives for all stakeholders (users, liquidity providers, governance, etc.)
- Consider game-theoretic attack vectors and mitigations
- Test incentive structures under various market conditions
Risk Management
- Implement risk parameters that can be adjusted via governance
- Use collateralization ratios appropriate to asset volatility
- Consider circuit breakers for extreme market conditions
- Develop contingency plans for black swan events
Protocol-Specific Security Patterns
Token Standards and Interactions
- Ensure compatibility with all expected token behaviors (rebasing, fee-on-transfer, etc.)
- Handle non-standard ERC20 implementations (missing return values, etc.)
- Use SafeERC20 wrapper for all token operations
- Consider gas costs for different token implementations
// Use SafeERC20 for token operations
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
contract TokenInteractions {
using SafeERC20 for IERC20;
function transferTokens(IERC20 token, address to, uint256 amount) external {
token.safeTransfer(to, amount);
}
}
Oracle Security
- Use decentralized oracles when possible
- Implement multiple oracle sources to reduce manipulation risk
- Include time-weighted average prices (TWAP) for price feeds
- Implement circuit breakers for extreme price movements
- Validate oracle data is recent and within expected ranges
// Simple oracle freshness and bounds check
function getVerifiedPrice(AggregatorV3Interface oracle) internal view returns (uint256) {
(, int256 price,, uint256 updatedAt,) = oracle.latestRoundData();
// Check for stale data
require(block.timestamp - updatedAt < maxOracleDelay, "Oracle data too old");
// Check for reasonable bounds
require(price >= minPrice && price <= maxPrice, "Oracle price out of bounds");
return uint256(price);
}
Liquidity Pool Security
- Implement slippage protection for all swaps
- Consider front-running protection mechanisms
- Use timelock delays for parameter changes
- Implement emergency withdrawals that bypass normal constraints
Flash Loan Attack Prevention
- Consider how your protocol might be exploited in a single transaction
- Implement reentrancy protection across all functions
- Use rate limiting for large operations
- Check for price manipulation when accepting external data
Governance Security
Secure Governance Design
- Implement timelock delays for governance actions
- Consider requiring multiple proposals for critical changes
- Use quadratic voting or other sybil-resistant mechanisms
- Implement guardrails that cannot be bypassed by governance
Parameter Safety
- Define safe ranges for all governable parameters
- Implement gradual parameter adjustments rather than step changes
- Include automatic limits on parameter changes per time period
- Have emergency mechanisms to revert to safe defaults
MEV Considerations
Miner (Maximal) Extractable Value Protection
- Implement commit-reveal schemes for sensitive operations
- Consider using privacy-preserving techniques for transaction data
- Implement batch operations to reduce MEV opportunity
- Design for fair ordering of transactions
Composability Security
Safe Protocol Integration
- Audit all integrated protocols before connecting to them
- Design for graceful failure if integrated protocols behave unexpectedly
- Implement circuit breakers that can disconnect from compromised protocols
- Test integration under various failure conditions
Cross-Protocol Risks
- Consider how changes in other protocols could affect yours
- Be aware of potential cascading liquidations across protocols
- Model shared risk when the same collateral is used across multiple protocols
- Monitor dependencies for security announcements and upgrades
Emergency Mechanisms
Circuit Breakers
// Multi-level circuit breaker pattern
contract AdvancedCircuitBreaker {
enum CircuitState { NORMAL, RESTRICTED, EMERGENCY }
CircuitState public currentState = CircuitState.NORMAL;
// Different levels of functionality restriction
modifier normalOperation {
require(currentState == CircuitState.NORMAL, "Not in normal operation");
_;
}
modifier notEmergency {
require(currentState != CircuitState.EMERGENCY, "In emergency state");
_;
}
// Functions with different restrictions
function normalFunction() external normalOperation {
// Only available in normal state
}
function essentialFunction() external notEmergency {
// Available in normal and restricted states
}
function emergencyWithdraw() external {
// Always available, even in emergency
}
}
Emergency Response
- Maintain a security incident response plan
- Have designated emergency multisig with limited powers
- Practice incident response with simulated attacks
- Establish communication channels for emergencies
DeFi security requires a combination of traditional smart contract security, economic security modeling, and cross-protocol risk assessment. Given the rapid evolution of the DeFi landscape, ongoing security monitoring and adaptation are essential.