Track 4 · Solidity foundations · lesson 4
Functions and visibility
10 min
Every function needs to say who may call it. Solidity will not guess, and getting this wrong is the second most common way contracts are drained.
The four keywords
public— callable by anyone, from outside or from inside the contract.external— callable only from outside. Slightly cheaper for functions taking large arguments, because the data can stay in calldata.internal— this contract and anything inheriting from it. Not the outside world.private— this contract only. Not even children.
internal and private functions do not appear in the ABI at all. They are
not hidden as a courtesy — there is genuinely no way to address them from
outside, because the contract exposes no entry point for them.
That is a real security boundary, unlike private on a variable, which stops
other contracts reading it but hides nothing from a person with a node.
Vault.solTweak
Loading editor…
Let the outside world read the balance.
Run the code to see what happens.
Nudge
The function exists. The problem is who is allowed to call it.
Show me the approach
A `private` function is not in the contract's ABI at all, so there is nothing for an outside caller to call.
Show me the code
Change `private` to `public` on the `balance()` function.
Explain the solution
`function balance() public view returns (uint256)`. Note the state variable can stay `private` — that only stops other *contracts* reading it directly, and anyone can still read the raw storage off-chain.
view, pure and what they cost
Alongside visibility, functions declare what they do to state:
view— reads state, changes nothing.pure— does not even read state.- neither — may write state.
Predict
You call a `view` function from your own wallet. What does it cost?
Check
When should you reach for `external` rather than `public`?
Worth remembering
- Four visibilities: public, external, internal, private. Solidity requires one on every function.
- internal and private functions are absent from the ABI, so nothing outside can call them.
- `view` reads state, `pure` touches none, neither means it can write.
- Calling a view function directly is free; calling one from inside a transaction is not.