Unit 5: Solidity
Solidity is a statically typed, contract-oriented language (released 2015, authored largely by Gavin Wood, Christian Reitwiessner and the Ethereum team) that compiles to bytecode run by the Ethereum Virtual Machine (EVM). Programs are deployed as smart contracts: self-contained accounts holding code and state that execute deterministically when transactions call them. This section fixes the vocabulary the rest of the unit relies on.
- Compilation target: Solidity source (
.sol) compiles to EVM bytecode plus an ABI (Application Binary Interface) that describes callable functions. - Deterministic execution: every node runs identical bytecode and must reach identical state, so sources of randomness and external I/O are forbidden.
- Gas: each EVM operation costs gas, paid in ether; a transaction reverts if it exceeds the supplied gas limit.
- Account types: externally owned accounts (controlled by private keys) and contract accounts (controlled by code).
- State persistence:
storagevariables live permanently on-chain;memoryandstackvalues exist only during a call. - Immutability: once deployed, bytecode cannot change, which forces attention to correctness before deployment.
II. Installing Remix IDE
The browser-based toolchain for writing, compiling and deploying contracts.
Remix is the reference IDE for Solidity, requiring no local installation because it runs entirely in the browser at remix.ethereum.org.
A. Installing Remix IDE (online Solidity compiler and development environment)
Remix lowers the entry barrier by bundling an editor, compiler and deployment tools into one web page.
- Access without install: open
https://remix.ethereum.org; the application loads as a single-page web app, so no package manager or runtime is needed locally. - File Explorer: create a workspace and add a file such as
Token.sol; Remix stores files in browser local storage by default. - Solidity Compiler plugin: choose a compiler version (e.g.
0.8.24), enable optimization, and press Compile; errors and warnings appear inline with line numbers. - Deploy & Run Transactions plugin: three environments are offered:
- Remix VM: an in-browser simulated chain with pre-funded test accounts, ideal for fast iteration.
- Injected Provider: connects to MetaMask to deploy on testnets (e.g. Sepolia) or mainnet.
- External HTTP provider: connects to a local node such as Ganache or Hardhat on
http://127.0.0.1:8545.
- Desktop option: Remix is also available as a downloadable Desktop IDE and via the
@remix-project/remixddaemon, which bridges the browser to a local folder for persistent file access.
III. Token Standards
Shared interfaces that let wallets and exchanges treat different tokens uniformly.
A token standard is an ERC (Ethereum Request for Comments) specification defining the minimum functions and events a contract must expose so external tools can interact with it predictably.
A. ERC-20 — the fungible token standard
ERC-20 (EIP-20, 2015) describes interchangeable tokens where every unit is identical in value, the model for most cryptocurrencies and governance tokens.
- Mandatory functions: the interface a compliant contract must implement:
SOLIDITYfunction totalSupply() external view returns (uint256); function balanceOf(address owner) external view returns (uint256); function transfer(address to, uint256 amount) external returns (bool); function approve(address spender, uint256 amount) external returns (bool); function allowance(address owner, address spender) external view returns (uint256); function transferFrom(address from, address to, uint256 amount) external returns (bool); - Events:
Transfer(from, to, value)andApproval(owner, spender, value)are emitted so off-chain indexers can track balances. - Approve/transferFrom pattern:
approvesets an allowance a third party (e.g. a DEX contract) may later spend viatransferFrom, enabling delegated transfers without exposing keys. - Decimals convention:
decimals()(usually 18) means balances are stored as integers;1token equals10**18base units, avoiding floating point.
B. ERC-721 — the non-fungible token standard
ERC-721 (EIP-721, 2018) describes unique, non-interchangeable tokens, each identified by a distinct uint256 tokenId, used for collectibles and digital deeds.
- Ownership mapping: every token has exactly one owner at a time, tracked by
ownerOf(tokenId);balanceOf(owner)returns a count, not a divisible amount. - Core functions:
SOLIDITYfunction ownerOf(uint256 tokenId) external view returns (address); function safeTransferFrom(address from, address to, uint256 tokenId) external; function approve(address to, uint256 tokenId) external; function setApprovalForAll(address operator, bool approved) external; - Metadata extension:
tokenURI(tokenId)returns a URI (often IPFS) pointing to JSON describing name, image and attributes. - Contrast with ERC-20:
- ERC-20: fungible,
transfermoves an amount; two holdings of equal size are indistinguishable. - ERC-721: non-fungible, transfers move a specific
tokenId; no two tokens are equivalent.
- ERC-20: fungible,
IV. Solidity Programming
The syntax and semantics for expressing contract logic.
Solidity code is organised into contracts, which group state variables, functions and events much like classes group fields and methods.
A. Solidity programming
A contract declares its compiler version, then its state and behaviour.
- File header: every file begins with a licence identifier and pragma:
SOLIDITY// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; - Value types:
uint256,int256,bool,address,bytes32, and fixed-sizeenum; since 0.8.0 arithmetic reverts on overflow by default. - Reference types:
string, dynamic arrays,struct, andmapping(keyType => valueType)for key-value storage. - Function visibility and mutability:
public/external: callable from outside;internal/privaterestrict access.view: reads but does not modify state;pure: touches no state;payable: may receive ether.
- Modifiers: reusable precondition checks, e.g.
modifier onlyOwner() { require(msg.sender == owner, "not owner"); _; }where_marks where the body executes. - Global variables:
msg.sender(caller),msg.value(ether sent),block.timestamp, used for access control and accounting. - Minimal worked example — a counter contract:
SOLIDITYcontract Counter { uint256 public count; // state in storage event Incremented(uint256 newCount); function increment() external { count += 1; // reverts on overflow emit Incremented(count); } }
Herecountpersists on-chain,incrementmutates it, and the event logs each change for off-chain listeners.
V. Smart Contract Management
Deploying, upgrading and controlling contracts over their lifecycle.
Because deployed bytecode is immutable, management focuses on access control, lifecycle events, and planned upgradeability.
A. Smart contract management
Managing a contract means governing who may act, how funds move, and how logic can evolve.
- Constructor and deployment: the
constructorruns once at deployment to set initial state such asowner = msg.sender; its code is not stored on-chain afterwards. - Access control: restrict sensitive functions with an owner pattern or role-based control (e.g. OpenZeppelin
Ownable,AccessControl), preventing unauthorised minting or withdrawal. - Error handling:
require(condition, "msg")validates inputs and refunds remaining gas;revert CustomError()saves gas versus string messages;assertguards invariants. - Events as audit trail: emitting events (
emit Transfer(...)) is the standard way to record state changes cheaply for front ends and analytics. - Upgradeability: since code cannot be edited, upgrade via the proxy pattern — a proxy contract holds state and
delegatecalls to a replaceable logic contract, so the address and data stay fixed while behaviour changes. - Library reuse: importing audited libraries (
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";) reduces bugs by inheriting tested implementations. - Gas and cost management: minimise
storagewrites (the costliest operation), pack variables into fewer slots, and prefercalldataovermemoryfor external function arguments.
VI. User Interface
Connecting a web front end to deployed contracts.
A smart contract is only usable when an interface lets non-technical users send transactions and read state through a wallet.
A. User interface
The front end communicates with the blockchain using a JavaScript library and a browser wallet that signs transactions.
- Wallet bridge: MetaMask injects a provider at
window.ethereum; the dApp requests account access witheth_requestAccountsbefore transacting. - JavaScript libraries:
ethers.jsorweb3.jswrap JSON-RPC calls; a contract object is built from its address and ABI. - Instantiating a contract:
JAVASCRIPTconst provider = new ethers.BrowserProvider(window.ethereum); const signer = await provider.getSigner(); const contract = new ethers.Contract(address, abi, signer);
The ABI tells the library how to encode function calls into transaction data. - Reads versus writes:
- Calls (reads):
view/purefunctions likebalanceOfrun locally, return instantly and cost no gas. - Transactions (writes): state-changing calls like
transferare signed by the wallet, broadcast, mined, and cost gas; the UI awaits the receipt before confirming.
- Calls (reads):
- Event subscription: the UI listens with
contract.on("Transfer", handler)to update balances in real time without polling. - Network awareness: the interface should detect
chainId, prompt the user to switch networks if it mismatches the deployment, and display pending/confirmed transaction status to manage expectations during block confirmation.
Did this save you a night before the exam?
LPU Notes is free, and it stays free. Ads cover part of the server bill. The rest comes out of a student's own pocket: the domain, the storage, and keeping the site up through the weeks everyone needs it at once.
The payment button didn't load. An ad blocker or a filtered network is the usual reason. to try again.
Nothing here is ever locked, and nothing unlocks. Chip in only if it was worth it. What it pays for →