1. use Check-effects-interactions

  2. underflow wrap around was a problem in solidity v0.6

  3. cross check all delegate calls for storage inconsistencies

  4. (bool success, ) = payable(previousKing).call{value: msg.value}(""); if (!success) { // Log the failure instead of reverting emit TransferFailed(previousKing, msg.value); }

    In any contract, we should never have a value transfer to another unknown contract as it assumes that the destination EOA/contract has the appropriate receive/fallback functions. Instead, there should be an option for the receiver to withdraw at their own will.

  5. when communicating with an external contract, focus on the following:

    1. does the getter retrieve a consistent value each time it is called?
    2. does it have an appropriate receive/fallback function ?
  6. extcodesize(caller())==0 check doesn’t make sense for safety whitelisting because it blocks all the well intentioned multisigs. Instead maintain a custom whitelist of allowed multisigs + EOAs.

  7. When imposing a constraint on an erc20 transfer, make sure that is it applied to _mint() and transferFrom() as well by simply overriding the update() function (according to the openzeppelin version 5)

  8. Contract address generation methods are different on some L2s due to difference in EVM.

  9. external user induced array manipulation might lead to storage layout exploits.

  10. Even though view and pure functions can’t modify the state they can have a conditional (?:) return. Therefore, don’t expect a view function to be just a ‘static view’ function.

  11. Ethernaut: puzzle wallet

    nested delegatecall in a transaction array

  12. (in the context of proxy contracts,) calling disableinitializers() in the implementation contract constructor is IMP!→ https://forum.openzeppelin.com/t/what-does-disableinitializers-function-mean/28730 and https://forum.openzeppelin.com/t/uupsupgradeable-vulnerability-post-mortem/15680

  13. Being a Responsible Multisig Signer: https://www.youtube.com/watch?v=YKGNcQXtMhg&list=PLh95371J-aVUhMxmHgs4U6OZ4jLbmsjp9&index=2

  14. don’t depend on error responses for verifying an event occurrence. this is because an error could be triggered unknowingly by an external contract call and get propagated back to the if condition if it is in the execution flow disregarding whether it is in the same function or not

  15. a calldata with a dynamic parameter (bytes or array) can have the offset for the param be any user defined value : https://docs.soliditylang.org/en/v0.8.19/abi-spec.html#examples

  16. starting in solc version 0.8.0, ABI coder v2 is enabled by default. This change added new safeguards so that the data type for parameters actually is checked

  17. Low-level calls in Solidity (.call(), .delegatecall(), .staticcall()) don’t revert automatically on failure but return a bool that must be explicitly verified to be true else revert.

  18. never use ecrecover without verifying that the signature is within the “non symmetric duplicable range”. just use https://github.com/OpenZeppelin/openzeppelin-contracts/blob/448efeea6640bbbc09373f03fbc9c88e280147ba/contracts/utils/cryptography/ECDSA.sol#L128-L154

  19. the vulnerable version didn’t cross check if there was an overflow. Therefore, use using SafeCast for uint256;

image.png