Solidity security. Reentrancy/CEI, access control, integer safety, oracle manipulation, flash loans, gas. Use when this capability is needed.
Install
npx skillscat add tomevault-io/tomes/solidity-security Install via the SkillsCat registry.
SKILL.md
Solidity Security
Reentrancy
CEI Pattern (Checks-Effects-Interactions) — NON-NEGOTIABLE
function withdraw(uint256 amount) external {
// CHECKS
require(balances[msg.sender] >= amount, InsufficientBalance());
// EFFECTS (update state BEFORE external call)
balances[msg.sender] -= amount;
// INTERACTIONS (external call LAST)
(bool success, ) = msg.sender.call{value: amount}("");
require(success, TransferFailed());
}Additional Protection
- Use
ReentrancyGuardfrom OpenZeppelin for complex functions - Cross-function reentrancy: guard shared state across multiple functions
- Read-only reentrancy: be aware of view functions reading stale state during callbacks
Access Control
| Pattern | Use When |
|---|---|
Ownable |
Single admin, simple contracts |
AccessControl (roles) |
Multiple roles, granular permissions |
| Multi-sig (Safe) | High-value operations, mainnet |
| Timelock | Governance, delayed execution |
- Never use
tx.originfor authorization — usemsg.sender - Check
msg.senderin modifiers, not function bodies (unless complex logic) - Consider 2-step ownership transfer (
Ownable2Step)
Integer Safety
- Solidity 0.8+ has built-in overflow/underflow protection
- Use
uncheckedblocks ONLY when overflow is mathematically impossible - Document WHY each
uncheckedblock is safe - Use
type(uint256).maxinstead of magic numbers - Watch for division-before-multiplication precision loss
Front-Running / MEV
| Attack | Mitigation |
|---|---|
| Sandwich attacks | Slippage protection, deadline params |
| Front-running | Commit-reveal schemes |
| MEV extraction | Use Flashbots, private mempools |
| Oracle manipulation | TWAP, multiple sources |
Oracle Security
- Never use spot price from a single DEX — use TWAP
- Chainlink: check
updatedAtfreshness,answeredInRound >= roundId - Handle oracle downtime gracefully (circuit breaker)
- Use multiple oracle sources with fallback logic
Delegate Call Risks
- Storage layout MUST match between proxy and implementation
- Never
delegatecallto untrusted addresses - Implementation contracts must call
_disableInitializers()in constructor - Watch for storage collision in proxy patterns
Flash Loan Vectors
- Assume any amount of tokens can be borrowed in a single transaction
- Don't rely on token balances for governance weight in the same block
- Use snapshot mechanisms for voting power
- Add time-weighted checks for critical operations
Storage Collision (Proxies)
- Use EIP-1967 storage slots for proxy state
- Never modify storage layout order in upgrades — only append
- Use
/// @custom:storage-locationfor namespaced storage (EIP-7201) - Run
forge inspectto verify storage layout before upgrade
Detailed References
- Vulnerability Checklist — SWC registry mapping
- Gas Optimization — Storage packing, calldata, custom errors
Converted and distributed by TomeVault — claim your Tome and manage your conversions.