OSSolidity.003 introduces the elementary data types and function parameters used to build Ethereum smart contracts. Solidity is statically typed: a variable’s type is specified, rather than inferred dynamically at every assignment. Integer values, booleans, Ethereum addresses, and string data represent different kinds of information, while function visibility and mutability determine how contract functions may be called and whether they can read or change state. The lesson uses a local Remix VM, with no real funds or public-chain deployment.
Earlier OSSolidity.001 introduced the Ethereum Virtual Machine. OSSolidity.002 introduced compiler pragmas, state variables and simple functions. The next step is recognizing which values belong in storage, which arrive through a function call, and how type declarations constrain operations. Solidity 0.8.38, released October 22, 2026, is the pinned reference version for the supplied sample. Official release announcement.
Learning objectives and prerequisites
- Distinguish value types such as
uint256,boolandaddressfrom reference types such asstring. - Identify a parameter in a function declaration and an argument supplied by a caller.
- Explain
storage,memoryandcalldatawithout confusing temporary data with persistent blockchain state. - Compare
external,public,internalandprivatevisibility. - Distinguish
pure,viewand a state-changing function. - Describe a basic access-control check using
msg.sender, and distinguish visibility from confidentiality. - Compile and interact with a teaching contract using an offline/local Remix VM.
- Inspect seven self-check functions and identify which results can be verified only after execution.
Prerequisites: Solidity source-file structure from OSSolidity.002, function calls, elementary integer arithmetic and command-line or browser-based editor use. The separate PHP error-handling lesson provides a useful comparison between validation failures in off-chain software and on-chain transaction reverts, but PHP is not required for Solidity study.
What Solidity value types represent
A Solidity value type is copied when assigned or passed as a normal argument. bool stores true or false. uint256 is a nonnegative unsigned integer with 256 bits; int256 represents signed integers. More narrowly sized forms such as uint8 are also supported, but selecting smaller widths does not automatically reduce execution gas in all contexts. address represents an Ethereum address and is not interchangeable with a text label.
uint256 public lastWatts; // Nonnegative integer
bool public hasReading; // Explicit validity/recorded flag
address public immutable instructor; // Deploying account
In the example, a zero reading is a valid integer value, so hasReading distinguishes ‘nothing recorded yet’ from ‘recorded zero’. State variables normally receive default values if not explicitly initialized, but those defaults do not establish that valid external data was received. The Solidity 0.8.38 type reference defines these elementary types and explains value-copy semantics.
Solidity deliberately lacks general-purpose floating-point arithmetic. A hardware reading that contains decimal fractions needs an explicit fixed-unit representation, for example storing 1250 as 1,250 milliwatts rather than pretending a floating-point watt value exists. The teaching contract uses whole watts solely to focus on types and calls. Applications must separately document units, precision, rounding and input provenance.
Dapp University, “Learn Blockchain & Solidity Development — Full Course 2024”, published December 28, 2023. See the variables and data types chapter beginning at approximately 17:23; remaining chapters include much more advanced financial examples not needed for the current lesson. Video identity and publisher verified from the public listing; embedding playback is not independently confirmed.
When data begins in a web interface, a browser HTML form can collect a device label or reading, but neither client-side validation nor a friendly input widget proves its accuracy. A smart contract must independently validate arguments before recording values, and any connection between a website and an Ethereum wallet requires additional authorization and transaction safeguards.
Strings and the three data locations
string, arrays and structs are reference types: their location matters. Solidity differentiates storage (persistent state), memory (temporary mutable data during a call), and calldata (non-modifiable input data, generally supplied with an external call). Data copied from temporary input into storage may incur persistent-state write costs. A copied string is not equivalent to its original location or lifetime.
string private _deviceLabel;
constructor(string memory initialLabel) {
_deviceLabel = initialLabel;
}
function rename(string calldata nextLabel) external {
_deviceLabel = nextLabel;
}
function summary() external view returns (string memory) {
return _deviceLabel;
}
The excerpt illustrates data location but omits authorization and input validation; use the complete secure-for-teaching version later in the lesson. The constructor receives a temporary memory string, rename receives read-only calldata input, and summary returns a value in memory. The official data-location specification explains the differences. No claim that every calldata parameter is cheaper is made; performance depends on ABI encoding and how data is used.
Function parameters, arguments and returns
A parameter is the named typed input in a function declaration; an argument is the actual value the caller supplies. For example, twice(uint256 watts) declares a parameter named watts. Calling twice(75) supplies the argument 75. The returns (uint256) clause declares the output type; 150 is the expected arithmetic result for the example.
function twice(uint256 watts) external pure returns (uint256) {
if (watts > 1000) revert ReadingTooLarge(watts);
return watts * 2;
}
// Expected result for twice(75): 150
// Expected behavior for twice(1001): revert
The limit is a deliberately arbitrary classroom value, not a genuine ASIC rating, data-center operating setpoint or safety threshold. For nonnegative values up to 1,000, multiplying by two stays far below the maximum uint256 value. Solidity 0.8.x normally checks arithmetic overflow and reverts rather than wrapping silently. Typed parameters improve predictability but do not authenticate the original measurement or decide whether an input is safe.
Visibility and state mutability
Solidity has different function visibility options. external functions are called through the external interface; public functions can also be called internally; internal functions are accessible to the contract and derived contracts; private functions are limited to the declaring contract. A public state variable generally gets a compiler-generated external getter. None of these keywords encrypt on-chain storage or prevent a blockchain observer from examining published transactions and data.
Function state mutability is a separate concept. view denotes that a function may read state but not modify it, while pure denotes that it should neither read nor change contract state. An ordinary state-changing function can write persistent variables and normally requires a transaction. Read-only calls through an off-chain provider need not create an on-chain transaction or incur a gas payment, while equivalent on-chain execution still consumes gas. Consult the official contracts reference.
function summary()
external view
returns (string memory label, uint256 watts, bool recorded)
{
return (_deviceLabel, lastWatts, hasReading);
}
// record(...) is external but state-changing:
// it writes lastWatts and hasReading.
The full ReadingBook teaching contract
The complete ReadingBook.sol file creates a tiny classroom ledger for invented equipment readings. The deployer becomes the immutable instructor address. Two state fields represent the most recent whole-watt value and whether a reading has been recorded. The persistent device label is a string, protected from changes by other callers. Public blockchain records remain observable even if a state variable is marked private.
A record(uint256 watts) call verifies msg.sender matches instructor, rejects a value above the deliberately fictional training limit, stores the accepted value and emits a ReadingRecorded event. rename(string calldata nextLabel) similarly restricts caller identity and checks the label length. summary() reads the stored label, numeric value and recorded flag, while twice() computes an isolated result.
// SPDX-License-Identifier: MIT
pragma solidity 0.8.38;
contract ReadingBook {
uint256 public constant TRAINING_LIMIT_WATTS = 1000;
address public immutable instructor;
uint256 public lastWatts;
bool public hasReading;
string private _deviceLabel;
error Unauthorized(address caller);
error ReadingTooLarge(uint256 supplied);
error InvalidLabelLength(uint256 length);
event ReadingRecorded(address indexed operator, uint256 watts);
constructor(string memory initialLabel) {
uint256 labelBytes = bytes(initialLabel).length;
if (labelBytes == 0 || labelBytes > 40)
revert InvalidLabelLength(labelBytes);
instructor = msg.sender;
_deviceLabel = initialLabel;
}
// Full verified source link above includes all function bodies.
}
The abbreviated listing shows the contract layout, not a complete executable file. Use the full source for compiling. It contains no payable function, fund transfer, oracle connector, token balance or production telemetry collector. It also does not implement a robust user-role system or upgrade mechanism. An event supplies an externally queryable log, but it is not a substitute for the stored lastWatts getter.
Local Remix VM compilation and execution
Open the official Remix IDE in a trusted browser. Create ReadingBook.sol and paste the full repository code. Select the Solidity compiler labeled 0.8.38, matching the exact pragma solidity 0.8.38;, and compile. In Deploy & Run, choose the local Remix VM rather than a public network or wallet connection. Do not attach real funds. Remix’s official Deploy & Run documentation explains local deployment and contract interactions.
Supply the constructor argument "miner-a". After successful local deployment, the expected initial values are lastWatts = 0 and hasReading = false. Call record(125) from the deploying account, and read back lastWatts = 125 with hasReading = true. Calling twice(75) should return 150 without changing storage. These are predicted results from the source, not outputs observed in an executed EVM session.
Change to another Remix VM account and attempt record(75). The transaction is expected to revert with Unauthorized. Switch back to the deployer and call record(1001); the transaction is expected to revert with ReadingTooLarge. For the classroom example, the original 125 reading should remain unchanged after either revert. Reverts roll back the failing call’s state changes, subject to ordinary EVM transaction semantics.
Test harness and verification boundaries
The companion ReadingBookChecks.sol is an isolated self-check contract. Import the file into the same Remix workspace and compile it alongside ReadingBook.sol. Deploy ReadingBookChecks into the Remix VM and call the seven public check functions separately. Each check creates a fresh classroom contract and returns true only if its assertions do not revert.
checkDefaults()— constructor arguments, defaults, owner and training limit.checkRecordAndZero()— distinguish a recorded zero from an untouched default, then store 125.checkPureFunction()— confirm doubled values for the input examples.checkRename()— verify a permitted label change.checkUnauthorizedCaller()— test a write attempted by a separate contract.checkReadingLimit()— test rejection above the classroom limit.checkEmptyConstructorLabel()— test rejection of an empty initial label.
A separate static-review.js file checks source-text structure with Node.js. The locally executed node --test static-review.js command passed 18 of 18 structural assertions, including type declarations, visibility markers, authorization checks, imports, and the existence of the seven Remix tests. The environment did not contain the Solidity compiler or a working EVM runtime; Solidity compilation and all seven Remix test results remain unverified. Structural checks cannot detect every compiler rejection or runtime security defect.
Chainlink, “Solidity Basics and Remix Tutorial — Lesson #1”, January 21, 2022. Patrick Collins demonstrates introductory Solidity concepts with the Remix IDE. The educational demonstration predates compiler 0.8.38, so the current Solidity manual controls syntax and security guidance. Video identified from the creator’s YouTube page; saved iframe playback is not independently confirmed.
Security and engineering limitations
- Contract visibility is not data secrecy: private variables still reside in observable blockchain state; do not put confidential credentials or unencrypted user secrets on chain.
- Caller authorization is necessary but not comprehensive: protecting
recordandrenamedoes not make the example audited or production-ready. - Calldata is not persistent storage: the input label is copied into
_deviceLabel; the variable does not simply point to transaction calldata after execution. - Pure/view is not an audit guarantee: compiler restrictions do not establish safe behavior for every integration or data source.
- Measurements require provenance: caller-submitted whole-watt numbers are not authenticated sensor telemetry; blockchain permanence cannot prove that submitted inputs were physically measured.
- Transactions have gas consequences: local VM work is instructional; real deployments and state-changing transactions may cost cryptocurrency and expose persistent records.
- Unchecked copy/paste is dangerous: version pinning, test coverage, threat modeling, access-control review and independent audits are necessary before any real-value or public-chain application.
The October 22, 2026 Solidity 0.8.38 release notes identify a Yul optimizer correctness fix affecting some earlier releases. Pinning the intended compiler version is therefore more than a formatting preference. A production build should also preserve compiler settings, target EVM, dependency revisions and source provenance.
Guided exercises and assessment
- Explain why
uint256is appropriate for the whole-watt example and why a negative value does not fit that type. - Change the sample to use
bool hasReadingand explain why zero alone cannot establish whether data was recorded. - Identify the argument and parameter in
twice(75)and predict the result. - Describe the lifetime and mutability differences between a
memoryconstructor string and acalldataexternal string. - Explain why
privatedoes not protect a stored label’s confidentiality. - Determine which calls change state and which are read-only, and why that affects transaction behavior.
- In the local Remix VM only, verify that a caller other than the deployer cannot record a reading.
- Test the upper boundary with 1,000 and 1,001 whole watts, then justify the chosen validation rule.
- Read each of the seven self-checks and state whether it measures a runtime behavior, a source property or both.
Answer key: uint256 is unsigned and accepts nonnegative whole numbers; the recorded flag distinguishes default zero from a real zero; watts is the parameter and 75 is the argument, yielding 150; memory is temporary mutable data while calldata is a non-modifiable call-data location; private limits source-level access rather than blockchain visibility; record and rename write state while summary reads and twice is pure; only the deployer should be authorized to record; 1,000 is permitted and 1,001 is expected to revert. Expected runtime outcomes must still be checked by compiling and executing in Remix.
Sources and curriculum continuation
Primary references include Solidity 0.8.38 Types, Contracts and Function Mutability, Solidity Cheatsheet, Remix Deploy & Run, and the Solidity compiler release statement. The two attributed videos provide additional introductory teaching rather than primary authority for the current compiler.
Data types specify the meaning and limits of values; parameter declarations define function inputs; visibility defines which calls are available; mutability describes interactions with state. Together, the concepts establish the first enforceable interfaces for a Solidity program. The next lessons can develop arrays, structs, mappings, events, and stronger access-control patterns without treating the introductory example as a deployed product.
Editor’s Note: OSSolidity.003 follows the published OSSolidity.002. The 1200 × 630 branded cover is original AI-generated editorial illustration, not an authentic compiler screenshot. Any displayed on-screen code is illustrative and is not the canonical full contract source. The small neon-green Bitcoinversus.Tech label appears at the bottom-left at approximately 10-point visual size. The linked source and seven Remix VM test functions were prepared for learner execution. Only the separate 18-case static Node.js review was executed locally and passed; Solidity 0.8.38 compilation, EVM deployment, Solidity test results, video playback, and mobile pixel inspection remain unverified. The device readings and thresholds are illustrative, not measured. No tokens, funds, or public-chain transactions were used.

To scan on mobile, display the QR on a separate screen or use a compatible wallet’s saved-image QR reader. Verify the destination and amount independently before sending funds.
We volunteer daily to ensure the information on this platform is Verifiably True. If you would like to support the research, please scan the QR code.
BitcoinVersus.Tech provides educational programming material and is not a financial advisor or source of audited production smart contracts.

Leave a Reply