Solidity Data Types
Lab deck 10: what Solidity and smart contracts are, the Remix IDE, the HelloWorld contract line by line, compiling and deploying in Remix, public getters, a first state-changing function, value types, state vs local variables, constant and immutable, and the five EVM data locations, with the StudentProfile and StudentData exercises.
Introduction to smart contractsSearch on YouTube
If Python is used to write normal programs, what do we use to write an Ethereum smart contract? Solidity.
| Normal program | Smart contract |
|---|---|
| Python program | Solidity program |
| Python interpreter | Solidity compiler |
| Computer / OS | EVM bytecode |
| Ethereum Virtual Machine |
- Solidity: a high-level programming language designed mainly for writing smart contracts on Ethereum-compatible blockchains.
- Smart contract: a program deployed to a blockchain, containing both data/state and functions/logic.
- EVM: the Ethereum Virtual Machine executes the compiled smart-contract bytecode.
Be clear that Solidity ≠ Ethereum, Solidity ≠ smart contract, and smart contract ≠ blockchain. Solidity is one language; the contract is the deployed program; the blockchain is where it lives.
Remix IDESearch on YouTube
Code is written in the Remix platform at app.remix.live, a browser IDE. It has a file explorer, editor, compiler, deployer and terminal.
Creating the first contract: Hello WorldSearch on YouTube
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
contract HelloWorld {
string public message = "Hello, Blockchain!";
}| Line | Meaning |
|---|---|
// SPDX-License-Identifier: MIT | Identifies the software license. Not blockchain functionality; metadata about the source code. |
pragma solidity ^0.8.20; | Tells the compiler which Solidity version the code is meant for. ^ means 0.8.20 or any later 0.8.x, but not 0.9.0. |
contract HelloWorld { ... } | A contract is the fundamental program unit in Solidity (like a class). |
string public message = "Hello, Blockchain!"; | A state variable |
The state variable line has four parts:
string public message = "Hello, Blockchain!";
data type visibility variable name initial valueState variableSearch on YouTube
In most programs, a variable lives in RAM and disappears when the program stops. In Solidity, variables declared at contract level (outside any function) are state variables. They are written permanently into blockchain storage, the EVM's "hard drive". This acts like a permanent row in a decentralised database.
Modifying a state variable costs real money (gas). Reading it is free.
Data typesSearch on YouTube
Solidity is statically typed: every variable's type must be declared explicitly at compile time. string is a dynamically sized array of characters used to hold text.
Visibility modifiers and "free" gettersSearch on YouTube
Visibility modifiers decide who or what may read or modify a variable. Declaring a state variable public makes the compiler generate a getter function automatically. You do not need to write getMessage(). Anyone in the world can then query the blockchain for the value.
Compiling in RemixSearch on YouTube
In the Solidity Compiler tab:
| Control | What it does |
|---|---|
| Hide warnings | Filters non-critical warnings (missing license, unused variables) so only fatal errors show |
| Compile HelloWorld.sol | Runs the compiler on the active file. A green check on the tab badge means zero errors. |
| Security Audit / Gas Audit | Static analysis that scans for common vulnerabilities (reentrancy, integer overflow patterns) and gas-heavy functions |
| Compile and Run script | Compiles and runs a deploy or test script (JavaScript/TypeScript with Ethers.js or Web3.js) from the workspace's scripts/ folder |
| Run Remix Analysis | Built-in static analysis for code quality, missing visibility specifiers and gas anti-patterns |
| Publish on IPFS / Swarm | Uploads source and metadata JSON to decentralised storage for public verification and hosting |
| ABI | Copies the Application Binary Interface |
| Bytecode | Copies the raw hexadecimal EVM instructions |
The ABI is a JSON array that defines all public functions, state variable getters, parameters and return types. Front ends (React, Web3.js, Ethers.js) need it to encode function calls.
The bytecode has two parts:
- Creation bytecode runs once during deployment. It executes the constructor and stores the runtime code on chain.
- Runtime bytecode is stored at the contract address. It runs whenever external accounts interact with the contract.
Deploying in RemixSearch on YouTube
The Deploy & Run Transactions tab deploys compiled bytecode to a simulated or live chain and lets you interact with its state.
| Control | What it does |
|---|---|
| Environment: Remix VM (Osaka, Cancun) | A sandboxed Ethereum chain in browser memory. Instant execution, simulated gas, state resets on reload. Ideal for teaching and quick tests. |
| Environment: Injected Provider (MetaMask) | Uses the browser wallet to deploy to public testnets (Sepolia, Holesky) or mainnet |
| Environment: Custom / External HTTP Provider | Connects to a local dev node on the host: Hardhat node, Anvil/Foundry, Ganache |
| Other environments listed | VM Fork, Dev, Base, WalletConnect |
| Fork | Simulates transactions against a snapshot of a real public chain |
| Reset | Wipes the Remix VM state back to block zero (balances and deployed contracts) |
| Account | 10 to 15 mock accounts, each pre-funded with 100 fake ETH. The choice sets msg.sender, the address that signs and pays. |
Click Deploy. What you observe:
- The account balance drops slightly. Writing to the blockchain is never free. Deployment used gas, and the EVM charged the deployer for storing the bytecode.
- Under Deployed Contracts the contract appears with its own address. It is an independent entity that can even hold its own cryptocurrency. Apps and users must target this address.
- The blue message button is the auto-generated read-only getter. Querying it costs zero gas.
- The terminal shows the permanent deployment record: sender address, bytecode payload (
data) and transaction hash.
State-changing functionsSearch on YouTube
A function is a self-contained block of code that performs a specific task.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
contract HelloWorld {
string public message = "Hello, Blockchain!";
function setMessage(string memory newMessage) public {
message = newMessage;
}
}function setMessage(...) public { ... }: unlike the read-only getter, this function changes permanent blockchain state. It cannot be called for free. The user must broadcast a transaction, sign it with a wallet, and pay gas.publicmeans anyone can call it and change the message.string memory newMessage: the memory keyword. Complex data (strings, arrays, structs) must state where it lives, because storage is expensive.memorymarks a temporary variable that exists only while the function runs and is then wiped.message = newMessage;: state overwrite. The temporary user input overwrites the permanent state variable.messageimplicitly lives in storage, so assigning a memory value to it moves temporary input into permanent blockchain history.
In Remix, the deployed contract now shows an orange setMessage button (a transaction) and a blue message button (a call). Enter "Welcome to IIIT Kottayam", click transact, then call message to see the new value.
Remix colour code: blue buttons are read-only calls (free). Orange buttons send transactions that change state (cost gas). Red buttons are payable.
Value typesSearch on YouTube
| Type | Used for | Example |
|---|---|---|
uint256 | Non-negative integers | 25 |
int256 | Positive / negative integers | -10 |
bool | True / false | true |
string | Text | "Alice" |
address | Ethereum address | 0x123... |
uint is an alias of uint256 and int of int256. Smaller sizes exist in steps of 8 bits (uint8 to uint256). Unassigned variables take a default value: 0, false, "" or the zero address.
Solidity has no floating-point type. Store a CGPA of 8.75 as an integer with a fixed scale, such as uint256 cgpa = 875; (two implied decimals).
State variable vs local variableSearch on YouTube
contract VariableDemo {
uint256 public stateNumber = 10; // state variable
function test() public {
uint256 localNumber = 20; // local variable
}
}Where a variable is declared decides its lifespan, its location in the EVM and its gas cost.
| State variable | Local variable | |
|---|---|---|
| Declared | At contract level, outside any function | Inside a function |
| Lifespan | Permanent: written into the ledger | Temporary: exists only while the function runs |
| Stored in | Storage (the "hard drive") | EVM stack; complex types like string go in memory |
| Gas cost | High: permanent storage on thousands of nodes | Lower |
Constant and immutableSearch on YouTube
uint256 public constant MAX_STUDENTS = 100;
address public immutable owner;- A constant must be set at declaration and cannot change after compilation.
- An immutable is assigned once, usually in the constructor, and cannot change afterwards.
Both are embedded in the contract's code instead of storage, which saves a lot of gas.
contract Registry {
uint256 public constant MAX_STUDENTS = 100;
address public immutable owner;
constructor() {
owner = msg.sender; // set once at deployment
}
}EVM memory managementSearch on YouTube
The EVM manages data in five locations, each with its own rules for mutability, lifespan and gas.
| Location | Analogy | Purpose | Lifespan | Use case |
|---|---|---|---|---|
| Storage | Hard drive | Permanently store contract state on the blockchain; persists across transactions and all nodes | Permanent | State variables: balances, ownership records, configuration |
| Memory | RAM | Temporarily hold mutable data while a function runs; wiped when it ends; not shared between calls | One function call | Processing strings, arrays, structs inside a function; building a string to return |
| Calldata | Read-only mailbox | Hold raw incoming data from outside; like memory but strictly read-only | One external call | An external user passes a string or array that the function does not modify; cheaper than memory |
| Stack | CPU registers | Low-level computation and small local values; hard limit of 1024 slots of 32 bytes each | One function call | Simple value types in a function, such as uint256 localNumber = 20; or bool isTrue = false; |
| Code | ROM | The compiled bytecode; immutable and permanent | Permanent | constant and immutable values, such as uint256 public constant MAX_SUPPLY = 1000; |
"Some Monkeys Climb Steep Cliffs": Storage, Memory, Calldata, Stack, Code.
function setName(string calldata newName) external { // read-only input, cheaper
name = newName; // copied into storage
}ExercisesSearch on YouTube
Exercise 1 and 2: StudentProfileSearch on YouTube
Exercise 1: create StudentProfile with state variables for student name, roll number and department. Write separate functions to set each one. Deploy in Remix and verify the stored values. Exercise 2: add a single function that takes name, roll number and department and updates all three at once.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
contract StudentProfile {
string public studentName;
uint256 public rollNumber;
string public department;
function setName(string memory _name) public {
studentName = _name;
}
function setRollNumber(uint256 _roll) public {
rollNumber = _roll;
}
function setDepartment(string memory _dept) public {
department = _dept;
}
// Exercise 2: update all three at once
function setProfile(string memory _name, uint256 _roll, string memory _dept) public {
studentName = _name;
rollNumber = _roll;
department = _dept;
}
}Exercise 3 and 4: StudentDataSearch on YouTube
Exercise 3: create StudentData with name, roll number, age, CGPA, graduation status, department and wallet address. Choose the best type for each, initialise them, deploy, and check the getters. Exercise 4: add functions to update name, age, CGPA and graduation status, and verify each change.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
contract StudentData {
string public studentName = "Alice";
uint256 public rollNumber = 2022101;
uint8 public age = 21;
uint256 public cgpa = 875; // 8.75, two implied decimals
bool public isGraduated = false;
string public department = "Cyber Security";
address public studentWallet = 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4;
// Exercise 4
function updateName(string memory _name) public { studentName = _name; }
function updateAge(uint8 _age) public { age = _age; }
function updateCgpa(uint256 _cgpa) public { cgpa = _cgpa; }
function updateGraduation(bool _status) public { isGraduated = _status; }
}Address literals must be in checksum (mixed-case) form or the compiler rejects them. The address above is Remix VM's first test account.
What to do and check in the lab:
- Open
app.remix.live, createHelloWorld.sol, compile (green check), and copy the ABI and bytecode to see their shape. - Deploy on Remix VM. Note the deployer's balance drop, the contract address, and the deployment record in the terminal.
- Click the blue
messagegetter (free). AddsetMessage, redeploy, transact a new message, and call the getter again. - Build
StudentProfile(separate setters, then one combined setter) andStudentData(choose types, then add update functions). Verify every change through the getters.
Quick self-testSearch on YouTube
Define Solidity, smart contract and EVM in one line each.
Solidity is a high-level language for writing smart contracts on Ethereum-compatible chains. A smart contract is a program deployed to a blockchain with data/state and functions/logic. The EVM executes the compiled contract bytecode.
What do the SPDX line and the pragma line do?
The SPDX line names the software license; it is metadata, not blockchain logic. The pragma tells the compiler which Solidity version the code targets (^0.8.20 = 0.8.20 up to below 0.9.0).
Viva: why is there a message button in Remix when you never wrote a getter?
The variable is declared public, so the compiler auto-generates a getter function with the same name.
Why does calling message cost no gas but setMessage does?
message only reads state, so a node answers locally without a transaction. setMessage changes stored state, so it needs a signed transaction mined by the network, and gas pays for that work.
What is the ABI and who needs it?
A JSON array describing all public functions, getters, parameters and return types. Front ends and libraries such as Ethers.js and Web3.js need it to encode calls to the contract.
Distinguish creation bytecode and runtime bytecode.
Creation bytecode runs once at deployment, executes the constructor, and stores the runtime code. Runtime bytecode lives at the contract address and runs on every interaction.
Compare the three Remix environments named in the deck.
Remix VM is an in-browser sandbox chain with instant, simulated gas that resets on reload. Injected Provider uses MetaMask to reach testnets or mainnet. Custom/External HTTP Provider connects to a local node such as Anvil, Hardhat or Ganache.
Viva: difference between a state variable and a local variable?
A state variable is declared at contract level, stored permanently in storage, and costly to write. A local variable is declared inside a function, lives on the stack (or memory for complex types) only during the call, and is cheap.
Difference between constant and immutable?
A constant is fixed at declaration and known at compile time. An immutable is assigned once, usually in the constructor, and fixed afterwards. Both are stored in the bytecode, not storage.
When should a function parameter use calldata instead of memory?
When it comes from an external caller and the function does not modify it. Calldata is read-only and avoids copying, so it saves gas.
How would you store a CGPA such as 8.75 in Solidity?
Solidity has no floating point, so store a scaled integer, for example uint256 cgpa = 875; with two implied decimals.
- Solidity source → compiler → EVM bytecode → executed by the EVM; Solidity, Ethereum, smart contracts and blockchains are different things.
HelloWorld: SPDX license line,pragma solidity ^0.8.20;,contract, and a state variable with type, visibility, name and initial value.publicstate variables get free auto-generated getters; writing state needs a signed transaction and gas.- Remix: compile (ABI, creation and runtime bytecode), deploy on Remix VM, Injected Provider or External HTTP Provider; accounts set
msg.sender. - Value types:
uint256,int256,bool,string,address; no floats. - State variables live in storage (permanent, costly); local variables live on the stack or in memory (temporary, cheap).
constantis fixed at compile time,immutableonce in the constructor; both live in code.- Five EVM data locations: storage, memory, calldata (read-only), stack (1024 × 32-byte slots), code.