Secureum Book
  • 🛡️Secureum Bootcamp
    • 🛡️Secureum Bootcamp
    • 🙌Participate
    • 📜History
  • 📚LEARN
    • Introduction
      • 🔷1. Ethereum Basics
        • 1.1 Ethereum: Concept, Infrastructure & Purpose
        • 1.2 Properties of the Ethereum Infrastructure
        • 1.3 Ethereum vs. Bitcoin
        • 1.4 Ethereum Core Components
        • 1.5 Gas Metering: Solving the Halting Problem
        • 1.6 web2 vs. web3: The Paradigm Shift
        • 1.7 Decentralization
        • 1.8 Cryptography, Digital Signature & Keys
        • 1.9 Ethereum State & Account Types
        • 1.10 Transactions: Properties & Components
        • 1.11 Contract Creation
        • 1.12 Transactions, Messages & Blockchain
        • 1.13 EVM (Ethereum Virtual Machine) in Depth
        • 1.14 Transaction Reverts & Data
        • 1.15 Block Explorer
        • 1.16 Mainnet & Testnets
        • 1.17 ERCs & EIPs
        • 1.18 Legal Aspects in web3: Pseudonymity & DAOs
        • 1.19 Security in web3
        • 1.20 web2 Timescales vs. web3 Timescales
        • 1.21 Test-in-Prod. SSLDC vs. Audits
        • Summary: 101 Keypoints
      • 🌀2. Solidity
        • 2.1 Solidity: Influence, Features & Layout
        • 2.2 SPDX & Pragmas
        • 2.3 Imports
        • 2.4 Comments & NatSpec
        • 2.5 Smart Contracts
        • 2.6 State Variables: Definition, Visibility & Mutability
        • 2.7 Data Location
        • 2.8 Functions
        • 2.9 Events
        • 2.10 Solidity Typing
        • 2.11 Solidity Variables
        • 2.12 Address Type
        • 2.13 Conversions
        • 2.14 Keywords & Shorthand Operators
        • 2.15 Solidity Units
        • 2.16 Block & Transaction Properties
        • 2.17 ABI Encoding & Decoding
        • 2.18 Error Handling
        • 2.19 Mathematical & Cryptographic Functions
        • 2.20 Control Structures
        • 2.21 Style & Conventions
        • 2.22 Inheritance
        • 2.23 EVM Storage
        • 2.24 EVM Memory
        • 2.25 Inline Assembly
        • 2.26 Solidity Version Changes
        • 2.27 Security Checks
        • 2.28 OpenZeppelin Libraries
        • 2.29 DAppSys Libraries
        • 2.30 Important Protocols
        • Summary: 201 Keypoints
      • 🔏3. Security Pitfalls & Best Practices
        • 3.1 Solidity Versions
        • 3.2 Access Control
        • 3.3 Modifiers
        • 3.4 Constructor
        • 3.5 Delegatecall
        • 3.6 Reentrancy
        • 3.7 Private Data
        • 3.8 PRNG & Time
        • 3.9 Math & Logic
        • 3.10 Transaction Order Dependence
        • 3.11 ecrecover
        • 3.12 Unexpected Returns
        • 3.13 Ether Accounting
        • 3.14 Transaction Checks
        • 3.15 Delete Mappings
        • 3.16 State Modification
        • 3.17 Shadowing & Pre-declaration
        • 3.18 Gas & Costs
        • 3.19 Events
        • 3.20 Unary Expressions
        • 3.21 Addresses
        • 3.22 Assertions
        • 3.23 Keywords
        • 3.24 Visibility
        • 3.25 Inheritance
        • 3.26 Reference Parameters
        • 3.27 Arbitrary Jumps
        • 3.28 Hash Collisions & Byte Level Issues
        • 3.29 Unicode RTLO
        • 3.30 Variables
        • 3.31 Pointers
        • 3.32 Out-of-range Enum
        • 3.33 Dead Code & Redundant Statements
        • 3.34 Compiler Bugs
        • 3.35 Proxy Pitfalls
        • 3.36 Token Pitfalls
        • 3.37 Special Token Pitfalls
        • 3.38 Guarded Launch Pitfalls
        • 3.39 System Pitfalls
        • 3.40 Access Control Pitfalls
        • 3.41 Testing, Unused & Redundand Code
        • 3.42 Handling Ether
        • 3.43 Application Logic Pitfalls
        • 3.44 Saltzer & Schroeder's Design Principles
        • Summary: 201 Keypoints
      • 🗜️4. Audit Techniques & Tools
        • 4.1 Audit
        • 4.2 Analysis Techniques
        • 4.3 Specification, Documentation & Testing
        • 4.4 False Positives & Negatives
        • 4.5 Security Tools
        • 4.6 Audit Process
        • Summary: 101 Keypoints
      • ☝️5. Audit Findings
        • 5.1 Criticals
        • 5.2 Highs
        • 5.3 Mediums
        • 5.4 Lows
        • 5.5 Informationals
        • Summary: 201 Keypoints
  • 🌱CARE
    • CARE
      • CARE Reports
  • 🚩CTFs
    • A-MAZE-X CTFs
      • Secureum A-MAZE-X
      • Secureum A-MAZE-X Stanford
      • Secureum A-MAZE-X Maison de la Chimie Paris
Powered by GitBook
On this page
  • Overflow/Underflow
  • Dividing before Multiplying
  • Strict Equalities
  • Tautologies & Contradictions
  • Boolean Constant
  • Boolean Equality
  1. LEARN
  2. Introduction
  3. 3. Security Pitfalls & Best Practices

3.9 Math & Logic

Overflow/Underflow

This security pitfall is related to the notion of overflows and underflows in Solidity smart contracts. This is applicable to any integer arithmetic that is used within the contracts which is very often encountered.

When such arithmetic is used in a way where the increments or decrements to those integer variables are done without checking for the bounds, then they could result in wrapped values where the value exceeds the maximum storage for that integer type and hence overflows or wraps to the lower end of that type or, If it's being decremented it could be decremented below zero in which case it results in wrapping to the maximum value of that integer type.

If those extremely high or extremely low data values resulting because of wrapping are invalid in the applications logic, then it is okay. But if it is not, if it's valid in the applications logic, then this could result in unexpected behavior in the best case or in the worst case it could result in some very serious vulnerabilities that can be exploited. We have seen multiple vulnerabilities and exploits led to overflow and underflow historically.

So the recommended best practice is to use the SafeMath libraries from OpenZeppelin that enforce the overflow and underflow checks during integer arithmetic or to use the latest Solidity versions greater than or equal to 0.8.0 that introduce check arithmetic by default.

Dividing before Multiplying

Another security pitfall or best practice related to integer arithmetic is dividing before multiplying. Solidity integer division might truncate the value of results therefore, if division is done before multiplication, then this may result in the loss of precision of the values being computed.

So the recommended best practice is to always do the multiplication operations first followed by any division that is required.

Strict Equalities

From a security perspective strict equalities are considered as dangerous in specific contexts of the smart content applications.

Strict equality is referred to the "==" operator or the "!=" operator as compared to the less stricter "<=" or ">=" operators.

When these strict equalities are applied to Ether or token values, then such checks could fail because the transferred Ether or tokens could be slightly less or greater than what the strict equalities expect or the balances computed could be different because of the different number of decimals expected or the precision of the operations being slightly different from the assumptions being made. Hence the use of strict equalities with such operands and operations is considered dangerous because they could lead to failed checks.

So the security best practice is to default to less stricter equalities and make sure that those constraints are satisfied as per the assumptions.

Tautologies & Contradictions

An interesting security consideration is that of tautologies and contradictions. A tautology is something that is always true whereas a contradiction is something that is always false.

Within smart contracts this can be found in certain primitives used, such as an unsigned integer variable x and then there is a predicate that checks, if x is greater than or equal to 0. This predicate because of x being an unsigned integer is a tautology it's always going to be true because x can't take a negative value.

The presence of such tautologies or contradictions in smart contracts indicates either flawed logic or mistaken assumptions made by the developer or these may just be redundant checks.

In either scenario these may be interesting from a security perspective, so it is something to be paid attention to and flagged as potential concerns.

Boolean Constant

The use of boolean constants true or false, directly in conditionals is unnecessary.

The reason for this is that if there's a conditional whose predicate is true, then that can be removed because that code block would get executed nevertheless and similarly, if the predicate is the boolean constant false, then that could be removed as well and along with the code in that associated block because that code would never execute because the conditional is always going to be false.

So these usages of boolean constants specifically within conditionals is indicative of flawed logic or assumptions or they could just be used in a redundant manner. The recommendation upon identifying such usage, it is removing those constants and any code blocks associated with them, so that it becomes simpler to read and to maintain.

Boolean Equality

An aspect related to boolean constants is that of boolean equality, this is where the boolean constants true or false are used within conditionals for an equality check, so the x variable is checked against the true constant.

This usage is redundant because the variable x can be used directly within the conditionals predicate without actually comparing it to true and both of them are equivalent.

So the use of the boolean constant true within the predicate is actually unnecessary, so while this may not be a big security consideration and perhaps indicative of the developer not fully understanding how Solidity booleans work.

It is interesting from an optimization perspective and certainly improves the readability aspect of the code.

Previous3.8 PRNG & TimeNext3.10 Transaction Order Dependence

Last updated 1 year ago

📚
🔏