Learning Objectives – after this chapter you will be able to:
- Explain the scope of local variables (block scope).
- Apply
public,internalandprivateto state variables. - Explain automatic getter functions.
- Explain why “private” data is still visible on the blockchain.
Scope of Variables
- Scope means the part of the program where a variable can be used.
- The scope of a local variable is limited to the block
{ ... }in which it is declared – from its declaration to the closing brace (the same rule as C99). It cannot be used outside that block. - State variables are available to all functions of the contract. Their visibility to other contracts is controlled by three visibility specifiers.
Visibility of State Variables
- public − can be accessed internally and also from outside the contract. For every public state variable the compiler automatically generates a getter function with the same name.
- internal − can be accessed only from inside the current contract and from contracts that inherit from it (without using
this). This is the default when no visibility is written. - private − can be accessed only inside the contract in which it is defined, not in derived (child) contracts.
| Visibility | Same contract | Derived contract | Other contracts / users | Getter created |
|---|---|---|---|---|
public | ✔ | ✔ | ✔ (via getter) | Yes |
internal (default) | ✔ | ✔ | ✘ | No |
private | ✔ | ✘ | ✘ | No |
external is a visibility for functions only (Chapter 15); it cannot be applied to state variables.
Private is not secret.
private and internal only stop other contracts from reading or changing a variable. All blockchain data is public, and anyone can read any storage slot with a node or block explorer. Never store passwords or secrets in a contract.Example : Visibility and Block Scope
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
contract Parent {
uint public publicData = 10; // getter publicData() is generated
uint internal internalData = 20; // visible here and in children
uint private privateData = 30; // visible only in Parent
function readPrivate() public view returns (uint) {
return privateData; // allowed: same contract
}
}
contract Child is Parent {
function readInherited() public view returns (uint) {
// return privateData; // compile error: private is not inherited
return publicData + internalData; // 10 + 20 = 30
}
function blockScope() public pure returns (uint) {
uint total = 0;
for (uint i = 1; i <= 3; i++) { // i exists only inside the loop
uint square = i * i; // square exists only inside this block
total += square;
}
// return square; // compile error: out of scope
return total; // 1 + 4 + 9 = 14
}
}
contract Outsider {
function readFromParent(Parent p) public view returns (uint) {
return p.publicData(); // only public data is reachable via its getter
}
}
Key Takeaways
- Local variables live only inside their block; state variables are available to the whole contract.
- public = everywhere (with a getter); internal = contract + children (default); private = this contract only.
- Visibility controls code access, not data privacy – everything on-chain can be read.
Download | Print E-Notes
The PDF E-Notes are the earlier printable version of this chapter. The notes on this page are the latest, revised version.
Question / Answer (15 questions)
Answer : Scope is the region of the program in which a variable can be used. Local variables are limited to their block; state variables are available throughout the contract, and their visibility controls access from other contracts.
Answer : From the point where it is declared to the end of the enclosing
{ } block, following C99 scoping rules. It cannot be used outside that block.Answer : public, internal and private.
Answer : internal.
Answer : Internal variables can be accessed inside the current contract and in contracts derived from it. Private variables can be accessed only inside the contract where they are defined, not in derived contracts.
Answer : For every public state variable the compiler generates an external view function with the same name that returns its value, e.g.
publicData(). For arrays and mappings the getter takes an index or key as a parameter.Answer : No. external is a visibility for functions only. State variables can be public, internal or private.
Answer : No. private only prevents other contracts from accessing the variable through code. All blockchain storage is public, so anyone can read the value using a node or block explorer.
Answer : Contract storage and transaction inputs are visible to everyone on the blockchain, so any stored password could be read and misused.
Answer : By calling its getter function through a contract reference, for example
p.publicData().Answer : square is declared inside the loop body block, so its scope ends at that block’s closing brace; it does not exist after the loop.
Answer : Yes. Internal members are accessible in the contract that defines them and in all contracts that inherit from it.
Answer : Directly by its name, like any internal variable (e.g.
publicData). Calling the getter with this.publicData() would make an external call, which is unnecessary and costs more gas.Answer :
function balances(address) external view returns (uint), which takes a key and returns the stored value.Answer : It defines which contracts can access or rely on a variable. Overly broad visibility can expose internal logic to misuse, while correct visibility keeps the contract’s design clear and reduces mistakes.
MCQ Test : Check Your Understanding (5 questions)
Select an option and press Check Answer, or answer all questions and press Submit Test to see your score. Each answer comes with an explanation.
Bibliography/References
The notes, questions and MCQs on this page are original explanations written for this course. The works listed below were consulted and are cited for attribution and further reading. Product names, logos and trademarks belong to their respective owners. Short quotations, where used, are marked and attributed.
- Solidity Team. (n.d.). Contracts (creating contracts, visibility and getters, function modifiers, constant and immutable, functions, events, custom errors, inheritance, abstract contracts, interfaces, libraries). Solidity Documentation. https://docs.soliditylang.org/en/latest/contracts.html
- Solidity Team. (n.d.). Expressions and Control Structures (if/else, loops, checked arithmetic, error handling, try/catch). Solidity Documentation. https://docs.soliditylang.org/en/latest/control-structures.html
- Solidity Team. (n.d.). Security Considerations. Solidity Documentation. https://docs.soliditylang.org/en/latest/security-considerations.html
- Modi, R. (2018). Solidity Programming Essentials: A beginner’s guide to build smart contracts for Ethereum and blockchain. Packt Publishing. ISBN 978-1-78883-138-3.