The goal of this repository is to create the most clear and concise collection of smart contract attack vectors, to improve overall ecosystem security.
- Front-Running AKA Transaction-Ordering Dependence
- DoS with Block Gas Limit
- DoS with (Unexpected) revert
- Forcibly Sending Ether to a Smart Contract
- Insufficient Gas Griefing
- Reentrancy
- Honeypot
- Integer Overflow and Underflow
- Timestamp Dependence
- Authorization Through tx.origin
- Floating Pragma
- Function Default Visibility
- Outdated Compiler Version
- Unchecked Call Return Value
- Unprotected Ether Withdrawal
- Unprotected Selfdestruct Instruction
- State Variable Default Visibility
- Uninitialized Storage Pointer
- Assert Violation
- Use of Deprecated Functions
- Delegatecall to Untrusted Callee
- Signature Malleability
Incorrect Constructor Namefixed since 0.4.22- Shadowing State Variables
- Weak Sources of Randomness from Chain Attributes
- Missing Protection against Signature Replay Attacks
- Requirement Validation
- Write to Arbitrary Storage Location
- Incorrect Inheritance Order
- Arbitrary Jump with Function Type Variable
- Presence of Unused Variables
- Unexpected Ether Balance
- Unencrypted Secrets
- Faulty Contract Detection
- Unclogged Blockchain Reliance
- Inadherence to Standards
- Unprotected NFT mint Callback
- Asserting EOA from Code Size
- https://github.com/ethereum/wiki/wiki/Safety
- https://swcregistry.io/
- https://eprint.iacr.org/2016/1007.pdf
- https://www.dasp.co/
- https://consensys.github.io/smart-contract-best-practices/
- https://github.com/sigp/solidity-security-blog
- https://solidity.readthedocs.io/en/latest/bugs.html
- https://github.com/pcaversaccio/reentrancy-attacks
If you notice any mistakes, typos or missing attacks/vulnerabilities, please feel free to open an issue or pull request. All contributions are very much appreciated.
Special thanks to RobertMCForster for many excellent contributions.
- Check for reentrancy risks
- Check whether the external call specifies the 1. the proper function and 2. the proper function arguments in the proper order for that function.
- Check for frontrunning and sandwich attack of the swap. This can happen when interacting with any liquidity pool (Uniswap, Sushi, Curve, Balancer, etc.)
- If a one-sided swap is performed before depositing into the liquidity pool (often named a "zap"), there may be dust left over because the first one-sided swap alters the balance and price of the liquidity pool assets.
- If tokens are transferred from a contract address, that contract must approve the tokens before the transferFrom is called, otherwise it will revert
- Safe math in Solidity 0.8.X does not protect against integer casting overflows and bitshift overflows
- Check all
require
andrevert
logic in case of unintentional reverts causing the user loss of gas
- Standard solidity ecrecover function is used without checking if the result is the zero address. Must check for zero address or use OZ
recover
from ECDSA library.
- If an ERC20 token list is used it must consider double entry point tokens, with past issues of this type here and here
- The ERC721 tokenId value must be unique. If the tokenId value is not a simple incrementing counter and instead uses a formula to calculate the tokenId, duplicate values may occur and lead to a revert
- If safeMint is used, check for reentrancy on the callback hook
- If any access controls are used (often in the form of modifiers) check functions that do not have any modifier to see if the modifier may have been forgotten.
- If spot price of a liquidity pool is used... just no
- Chainlink oracle data may be stale. The roundId and timestamp should be checked.
- Any purchase or swap function should have slippage protection. This is normally a user-specified function argument.
- Compound does not strictly follow the checks-effects-interactions pattern to avoid reentrancy. This can lead to reentrancy problems if tokens with callbacks (ERC721, ERC777, etc.) are used.
- Compound whitelists tokens and can avoid ERC20 tokens with unusual behavior. If a fork of compound does not whitelist tokens, issues can exist with fee-on-transfer tokens among others.
- UUPS proxies MUST be initialized after deployment. Forgetting to initialize the proxy led to the first $10 million bug from Immunefi and many other past bugs.
- State variable layout must be followed when delegatecall is used, otherwise this leads to problems
- Many OpenZeppelin upgradeable contracts need to be initialized in the importing contract's constructor.
- Does the snapshot process prevent a user from flashloaning tokens to make a large number of votes or receive a lot of yield?
- Does the snapshot process prevent a user from voting (or redeeming yield), transferring tokens, and voting again (or redeeming yield)?
- If the voting happens off-chain, is proper planning and integration with snapshot.org applied? Which voting strategy is used? Will voting delegation be added with the
setDelegate
function?
- Is there a way that a user can become undercollateralized, reducing the incentive to pay their debt?
- If cryptopunks are supported (which requires custom code), it should protect against this frontrun attack vector.