Solidity Tutorial
A Comprehensive Beginner's Guide to Smart Contract Development
Learn the fundamentals of Solidity programming
Build smart contracts on Ethereum and EVM-compatible blockchains
What is Solidity?
Solidity is a statically typed, contract-oriented programming language used to write smart contracts on Ethereum and other EVM-compatible blockchains.
Key Characteristics:
- Statically Typed: Variable types are known at compile time
- Contract-Oriented: Built specifically for smart contracts
- EVM Compatible: Runs on Ethereum Virtual Machine
- High-Level Language: Similar to JavaScript and C++
Basic Contract Structure:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract HelloWorld {
string public greeting = "Hello, Blockchain!";
}
Contract Classes & Functions
Defining a Contract with Functions:
contract Bank {
uint public balance;
function deposit(uint amount) public {
balance += amount;
}
function withdraw(uint amount) public {
if (amount <= balance) {
balance -= amount;
}
}
}
Using require() for Better Error Handling:
function safeWithdraw(uint amount) public {
require(amount <= balance, "Insufficient balance");
balance -= amount;
}
Visibility Specifiers
public
Accessible externally and internally. Creates automatic getter functions for state variables.
private
Accessible only inside the contract where it's defined. Not visible to derived contracts.
internal
Accessible in current contract and derived contracts. Similar to protected in OOP.
external
Accessible only from outside the contract. More gas-efficient for large data.
Best Practice: Use the most restrictive visibility that meets your needs for better security and gas optimization.
Global Variables
Common Global Variables:
- msg.sender: Address of the caller
- msg.value: Ether sent with transaction
- block.timestamp: Current block timestamp
- tx.origin: Original sender of transaction
- block.number: Current block number
- gasleft(): Remaining gas
- block.coinbase: Miner's address
- block.difficulty: Block difficulty
Example Usage:
function getCallerInfo() public view returns(address, uint) {
return (msg.sender, block.timestamp);
}
function miningInfo() public view returns(uint, address) {
return (block.number, block.coinbase);
}
Inheritance & Abstract Contracts
Basic Inheritance:
contract A {
function greet() public pure returns (string memory) {
return "Hello from A";
}
}
contract B is A {
function greetB() public pure returns (string memory) {
return "Hello from B";
}
}
Abstract Contracts:
abstract contract Animal {
function sound() public view virtual returns (string memory);
}
contract Dog is Animal {
function sound() public pure override returns (string memory) {
return "Woof!";
}
}
Multiple Inheritance
Solidity supports multiple inheritance:
contract X {
function foo() public pure returns (string memory) {
return "X";
}
}
contract Y {
function bar() public pure returns (string memory) {
return "Y";
}
}
contract Z is X, Y {
// Z inherits from both X and Y
// Can call both foo() and bar()
}
Important: Solidity uses C3 linearization to resolve inheritance conflicts. Order matters when specifying multiple inheritance!
Libraries
Creating a Library:
library Math {
function add(uint a, uint b) internal pure returns (uint) {
return a + b;
}
function multiply(uint a, uint b) internal pure returns (uint) {
return a * b;
}
}
Using Libraries:
contract Calculator {
using Math for uint;
function addNums(uint x, uint y) public pure returns (uint) {
return x.add(y);
}
function multiplyNums(uint x, uint y) public pure returns (uint) {
return x.multiply(y);
}
}
Data Types & Optimization
Common Data Types:
- uint: Unsigned integer
- int: Signed integer
- bool: Boolean (true/false)
- address: Ethereum address
- string: UTF-8 encoded string
- bytes: Dynamic byte array
- struct: Custom data structure
- mapping: Key-value store
Gas Optimization Tips:
- Use uint256 for consistency (EVM word size)
- Minimize storage writes (most expensive operation)
- Use calldata for function inputs
- Pack variables when possible
Variable Packing Example:
struct PackedData {
uint128 data1; // 16 bytes
uint128 data2; // 16 bytes - fits in single storage slot
}
Debugging Tools
Common Debugging Tools:
Hardhat
console.log support and detailed stack traces for comprehensive debugging
Remix IDE
Built-in debugger with variable inspector and step-through debugging
Truffle
truffle test with Mocha framework for unit testing and debugging
Hardhat Debugging Example:
import "hardhat/console.sol";
contract DebugExample {
function test(uint x) public {
console.log("X value is:", x);
}
}
Pro Tip: Always test your contracts thoroughly and use proper debugging tools to catch issues early!
Summary
What We've Covered:
Solidity Basics
Contract structure, functions, and syntax fundamentals
Visibility & Access
Public, private, internal, and external visibility specifiers
Global Variables
msg.sender, block.timestamp, and other blockchain context
Inheritance
Single, multiple, and abstract contract inheritance
Libraries
Code reusability and modular programming
Optimization
Gas optimization techniques and best practices
Next Steps: Practice with Remix IDE, explore advanced topics like events and modifiers, and start building your own smart contracts!
1 / 11