#solidity
Rulesets (2)
Ruleset for smart contract security, contributed by Decurity (https://www.decurity.io/).
Rules (49)
To guarantee arguments type safety it is recommended to use `abi.encodeCall` instead of `abi.encodeWithSelector`.
By demanding that the receiver of the owner permissions actively accept via a contract call of its own, `Ownable2Step` and `Ownable2StepUpgradeable` prevent the contract ownership from accidentally being transferred to an address that cannot handle it.
Caching the array length outside a loop saves reading it on each iteration, as long as the array's length is not changed during the loop.
<x> += <y> costs more gas than <x> = <x> + <y> for state variables.
Uninitialized variables are assigned with the types default value. Explicitly initializing a variable with its default value costs unnecessary gas.
Consider swapping variables using `($VAR1, $VAR2) = ($VAR2, $VAR1)` to save gas
Consider making costructor payable to save gas.
Replace state variable reads and writes within loops with local variable reads and writes.
A lot of times there is no risk that the loop counter can overflow. Using Solidity's unchecked block saves the overflow checks.
Consider using custom errors as they are more gas efficient while allowing developers to describe the error in detail using NatSpec.
Using multiple require statements is cheaper than using && multiple check combinations. There are more advantages, such as easier to read code and better coverage reports.
Using nested is cheaper than using && multiple check combinations. There are more advantages, such as easier to read code and better coverage reports.
Consider using the prefix decrement expression whenever the return value is not needed. The prefix decrement expression is cheaper in terms of gas.
Consider using the prefix increment expression whenever the return value is not needed. The prefix increment expression is cheaper in terms of gas.
Shortening revert strings to fit in 32 bytes will decrease gas costs for deployment and gas costs when the revert condition has been met.
Contract can be destructed by anyone in $FUNC
An attacker may perform call() to an arbitrary address with controlled calldata
msg.sender is not being used when calling erc20.transferFrom. Example - Alice approves this contract to spend her ERC20 tokens. Bob can call function 'a' and specify Alice's address as the from parameter in transferFrom, allowing him to transfer Alice's tokens to himself.
$VAULT.getPoolTokens() call on a Balancer pool is not protected from the read-only reentrancy.
$VAR.getRate() call on a Balancer pool is not protected from the read-only reentrancy.
Possible arithmetic underflow
Price oracle can be manipulated via flashloan
Function borrowFresh() in Compound performs state update after doTransferOut()
Function sweepToken is allowed to be called by anyone
$POOL.get_virtual_price() call on a Curve pool is not protected from the read-only reentrancy.
An attacker may perform delegatecall() to an arbitrary address.
abi.encodePacked hash collision with variable length arguments in $F()
Anyone can burn tokens of other accounts
Custom ERC20 implementation exposes _transfer() as public
ERC677 callAfterTransfer() reentrancy
Custom ERC721 implementation lacks access control checks in _transfer()
ERC721 onERC721Received() reentrancy
ERC777 tokensReceived() reentrancy
UniswapV3 adapter implemented incorrect extraction of path parameters
blockhash(block.number) and blockhash(block.number + N) always returns 0.
Keep3rV2.current() call has high data freshness, but it has low security, an exploiter simply needs to manipulate 2 data points to be able to impact the feed.
$F with constant msg.value can be called multiple times
The code must not contain any of Unicode Direction Control Characters
No slippage check in a Uniswap v2/v3 trade
Potential signature malleability in $F
Oracle price data can be submitted by anyone
Proxy declares a state var that may override a storage slot of the implementation
transferFrom() can steal allowance of other accounts
setMultipleAllowances() is missing onlyOwner modifier
Oracle update is not restricted in $F()
A specially crafted calldata may be used to impersonate other accounts
Parameter "from" is checked at incorrect position in "_allowances" mapping
Uniswap callback is not protected
Unrestricted transferOwnership