Data Types & Variables
Solidity is statically typed — every variable must have a declared type. Understanding value types vs reference types and storage vs memory is critical for writing correct and gas-efficient contracts.
Value Types
Value types are copied when assigned or passed to functions.
Integers:
- uint8, uint16, ..., uint256 (unsigned, default: uint256)
- int8, int16, ..., int256 (signed)
- uint (alias for uint256) — most common
- Arithmetic: overflow reverts in ^0.8.0 (SafeMath is no longer needed!)
Boolean:
- bool — true or false
- Operators: &&, ||, ! (short-circuit evaluation)
Addresses:
- address — 20-byte Ethereum address
- address payable — can receive ETH via .transfer() and .send()
- methods: .balance, .call(), .transfer(), .send()
Fixed-size bytes:
- bytes1 through bytes32 — efficient for small fixed data
- bytes32 is commonly used for hashes, identifiers
Enums:
- User-defined type with named integer values
- Stored as uint8 internallyStorage vs Memory vs Calldata
Solidity has three data locations — must be specified for reference types:
storage — Persistent on-chain storage (expensive: 20,000 gas for new slot)
- State variables are always storage
- Modifying storage = sending a transaction
memory — Temporary, exists only during function execution (cheap)
- Function arguments and local variables use memory
- Cleared after function returns
calldata — Read-only, external function arguments (cheapest)
- Use for external function string/array/bytes params
- Saves ~200 gas per read vs memory copy
Rule of thumb:
- External function params: calldata
- Internal function params: memory
- State variables: storage (implicit)Common Mistakes
- Using storage reference when you want a memory copy — string storage x = arr[0] creates a reference; modifying x modifies arr[0]
- Using int for token amounts — always use uint256. Negative token balances make no sense and introduce complexity.
- Dividing before multiplying — Solidity has no decimals. Always multiply first: (a * b) / c, never (a / c) * b, to avoid precision loss.
- Comparing strings with == — Solidity cannot directly compare strings. Use keccak256(abi.encodePacked(a)) == keccak256(abi.encodePacked(b)) instead.
Tip
Tip
Practice Data Types Variables in small, isolated examples before integrating into larger projects. Breaking concepts into small experiments builds genuine understanding faster than reading alone.
Once deployed, smart contracts are immutable — code is law
Practice Task
Note
Practice Task — (1) Write a working example of Data Types Variables from scratch without looking at notes. (2) Modify it to handle an edge case (empty input, null value, or error state). (3) Share your solution in the Priygop community for feedback.
Quick Quiz
Common Mistake
Warning
A common mistake with Data Types Variables is skipping edge case testing — empty inputs, null values, and unexpected data types. Always validate boundary conditions to write robust, production-ready web3 code.
Key Takeaways
- Solidity is statically typed — every variable must have a declared type.
- Using storage reference when you want a memory copy — string storage x = arr[0] creates a reference; modifying x modifies arr[0]
- Using int for token amounts — always use uint256. Negative token balances make no sense and introduce complexity.
- Dividing before multiplying — Solidity has no decimals. Always multiply first: (a * b) / c, never (a / c) * b, to avoid precision loss.