Anatomy of a Solidity File
Every Solidity source file begins with an SPDX license comment and a pragma directive that pins the compiler version, such as pragma solidity ^0.8.20. Inside the file you declare one or more contracts using the contract keyword, and within a contract you place state variables, functions, events, modifiers, and custom types. Statements end with semicolons and blocks use curly braces, much like C or JavaScript. The compiler reads this structure top to bottom, and because Solidity is statically typed, every variable must declare its type explicitly, letting the compiler catch many mistakes before the contract ever reaches the chain.
Cricket analogy: Like a scorecard with fixed sections for batting, bowling, and extras that every match sheet follows, a Solidity file follows a fixed structure of pragma, contract, and members.
State, Local, and Global Variables
Solidity distinguishes three kinds of variables by where they live. State variables are declared at the contract level and are permanently stored in the contract's storage on the blockchain, so writing to them costs significant gas and their values persist between transactions. Local variables are declared inside functions and exist only for the duration of that call, held in memory or on the stack and never written to storage. Global variables are built-in values the EVM injects, such as msg.sender (the caller's address), msg.value (ether sent with the call), and block.timestamp (the current block's time), giving contracts context about the transaction and chain.
Cricket analogy: State variables are like the official scoreboard that persists all match, local variables are like a fielder's mental note for one over, and globals like msg.sender are the umpire telling you who is on strike right now.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
contract Counter {
// State variable: stored permanently, publicly readable
uint256 public count;
address public owner;
constructor() {
owner = msg.sender; // global variable: who deployed the contract
}
function increment(uint256 by) external {
uint256 newCount = count + by; // local variable, memory/stack only
count = newCount; // write to storage costs gas
}
}Visibility Modifiers
Visibility controls who can access a function or state variable. Functions can be public (callable internally and externally), external (callable only from outside the contract), internal (callable within the contract and its descendants), or private (only within the defining contract). State variables can be public, internal, or private, and marking one public makes the compiler generate an automatic getter function. Crucially, private and internal do not mean secret: because all blockchain data is publicly visible, anyone can read a private variable's value by inspecting storage, so visibility limits code access, not data confidentiality.
Cricket analogy: Like team roles where the captain sets the field for everyone (public) but the coach's private notes stay in the dressing room, visibility sets who can call code, yet the scoreboard data is always public.
Marking a variable private does not make its value confidential. All storage on a public blockchain is readable by anyone with a node, so never store secrets like passwords or private keys in contract state expecting them to be hidden.
For reference-type function parameters and local variables (arrays, structs, strings, mappings), you must specify a data location: storage, memory, or calldata. calldata is a read-only, gas-efficient location for external function arguments.
- Every file opens with an SPDX license comment and a pragma pinning the compiler version.
- Solidity is statically typed, so every variable must declare its type explicitly.
- State variables persist in storage on-chain and cost gas to write; they survive between transactions.
- Local variables live only during a function call in memory or on the stack.
- Global variables like msg.sender, msg.value, and block.timestamp give transaction and chain context.
- Visibility (public, external, internal, private) controls code access, not data confidentiality.
- Reference types require an explicit data location: storage, memory, or calldata.
Practice what you learned
1. Where are state variables stored?
2. What does the global variable msg.sender represent?
3. Which statement about the private visibility modifier is correct?
4. What effect does marking a state variable public have?
5. Which data location is read-only and most gas-efficient for external function arguments?
Was this page helpful?
You May Also Like
What Is Solidity?
Solidity is a statically typed, contract-oriented programming language for writing smart contracts that run on the Ethereum Virtual Machine and compatible blockchains.
Solidity Data Types and Value Types
Explore Solidity's value types and reference types, including sized integers, booleans, addresses, bytes, enums, arrays, structs, and mappings, and how they are copied and stored.
Your First Smart Contract
Write, compile, and deploy a complete storage contract, learning about the constructor, functions, events, access control, and the payable keyword along the way.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics