What exactly is a Smart Contract audit?
A Smart Contract audit is the process investigating carefully a piece of code, in this case a Solidity contract to find bugs, vulnerabilities and risks before the code is deployed and used in the main Ethereum’s network where it won’t be modifiable. It’s just for discussion purposes.
- Feature of blockchain:
- EVM limits:
- Do consider gas limit
- Do consider call stack depth limit (Update: EIP150 fixed this problem, removing the possibility of a call stack attack by reducing the amount of gas each recursive call gets.)
Write simple and modular code and order your function code: conditions, actions, interactions
- common:
- Consider using SafeMath library
- Enforce invariants with assert()
- Use assert() and require() properly
- Beware rounding with integer division
- Be aware of the tradeoffs between abstract contracts and interfaces
- Keep fallback functions simple
- Explicitly mark visibility in functions and state variables
- Lock pragmas to specific compiler version
- Differentiate functions and events
- Prefer newer Solidity constructs
- Be aware that 'Built-ins' can be shadowed
- Avoid using tx.origin
- Multiple Inheritance Caution
- conditions: Fail as early and loudly as possible
- Don’t assume contracts are created with zero balance
- Remember that Ether can be forcibly sent to an account
- Check order of timestamps
- Check timestamps, if you have logic associated with timestamps
- actions:
- interactions:
- Don't use unnecessary low level call
- Use caution when making external calls
- Mark untrusted contracts
- Be aware of the tradeoffs between send(), transfer(), and call.value()()
- Handle errors in external calls
- Favor pull over push for external calls
- After interacting with other contract, check the state variable integrity.
- Using pragma version latest
- Consider variable size (i.e
uint8
,uint16
, ...,uint256
) - Consider solidity automatically creates getter functions for state variable
- Delete unused variables
- Delete variables that have the same information
- If you can infer a variable value through another variable, delete that variable
- Do not use unnecessary temp variables
- MAGIC NUMBER uses a constant
- A constant of the same name must not have a different value in another contract
- If you can infer
true
/false
as an integer value, usebool
- If the values of the various state variables must maintain the relationship, consider implementing a mechanism to assert the integrity of invariants
- Consider difference between
string
andbyte
- Validate the paramter
- Multiple functions in the same logic make one function.
- Delete unused function
- If the return value is not used, remove the return parameter.
- Use
view
if the function doesn't change state. - Use
pure
if the function doesn't even read state. - If you expect that the function will only ever be called externally, use
external
- If the modifier is used only once, it is confusing rather than useful
- Consider whether logic such as the modifier's logic is in the function
- Consider using modifiers when using common logic in multiple functions
- for loop
- Consider reviewing all for-loops and ensure that array maximum lengths are checked on iteration.
- Consider the situation where loop exits out of gas.
- Make sure that increment variable does not overflow.
- Naming with clear meaning
- It is recommended that the name of the
event
and the name of thefunction
be different.
- Consider using scientific notation to declare numeric constants to avoid typos
- ERC20 compliance
- Emit the event for initial supply creation, minted tokens
- Possible attack vector on the approve/transferFrom functionality of ERC20 tokens
- It should be the same as the white paper.
- Consider implementing claimTokens function
- Implement claimTokens function to prevent ERC20 tokens from being sent inadvertently.
- Reentrancy attack
- Over and under flows
- Replay attack
- Reordering attack
- Short address attack