🏗️ Smart Contracts: Contract Development
Imagine you’re building a magical vending machine. Once you set the rules, it runs forever without anyone needing to press buttons behind the scenes. That’s a smart contract!
🎭 The Story: Building Your Robot Helper
Think of a smart contract like building a robot helper that lives on the blockchain. Today, we’ll learn how to:
- Teach your robot to understand instructions (ABI)
- Give it commands (Function Calls)
- Send it on missions (Transactions)
- Help it keep a diary (Events & Logs)
- Make it run efficiently (Gas Optimization)
- Upgrade it when needed (Upgradability)
- Use a helper to talk to it (Proxy Patterns)
- Create robot factories (Factory Patterns)
Let’s begin our adventure!
📋 Contract ABI: The Robot’s Instruction Manual
What is ABI?
ABI stands for Application Binary Interface.
Think of it like this: You speak English, but your robot speaks in beeps and boops (binary code). The ABI is like a translation book that helps you talk to each other!
Simple Example
When you want to tell your robot “say hello”, the ABI translates it:
{
"name": "sayHello",
"type": "function",
"inputs": [],
"outputs": [
{"type": "string"}
]
}
This says: “There’s a button called sayHello. Press it, and you get words back!”
Real-Life Analogy
📱 Your TV Remote
- Each button has a specific job
- Button 1 = Channel 1
- Volume Up = Louder sound
The ABI is your contract’s “remote control manual” — it tells everyone which buttons exist and what they do!
Key Parts of an ABI Entry
| Part | What It Means | Example |
|---|---|---|
| name | The function’s name | transfer |
| type | What kind of thing | function |
| inputs | What you give it | address, amount |
| outputs | What it gives back | success: true |
📞 Function Calls: Talking to Your Robot
Two Ways to Talk
Your robot understands two types of commands:
1. Read Commands (Free! No gas needed)
Just asking questions. Like asking “What’s the time?”
function getBalance(address user)
public view returns (uint256) {
return balances[user];
}
The word view means “just looking, not changing anything!”
2. Write Commands (Costs gas)
Making changes. Like saying “Add 5 to my score!”
function addScore(uint256 points)
public {
scores[msg.sender] += points;
}
How Function Calls Work
graph TD A["You"] -->|Call Function| B["Your Wallet"] B -->|Encode with ABI| C["Transaction Data"] C -->|Send to Network| D["Smart Contract"] D -->|Execute Code| E["Result"]
Example: Calling a Function
You want to send 10 tokens to Alice:
- Your instruction: “Send 10 tokens to Alice”
- ABI encodes it:
0xa9059cbb000000... - Network processes: Miners/validators run the code
- Done!: Alice has 10 more tokens
💸 Contract Transactions: Sending Your Robot on Missions
What’s a Transaction?
A transaction is like a sealed envelope you send through the blockchain mail system. It contains:
- From: Your address
- To: The contract’s address
- Data: The encoded function call
- Value: ETH to send (if any)
- Gas: Fuel money for the journey
Transaction Lifecycle
graph TD A["Create Transaction"] --> B["Sign with Key"] B --> C["Broadcast to Network"] C --> D["Miners Pick It Up"] D --> E["Execute in EVM"] E --> F["State Changes"] F --> G["Receipt Generated"]
Simple Transaction Example
// Sending a transaction
const tx = await contract.transfer(
"0xAlice...", // to whom
100 // how much
);
// Wait for confirmation
const receipt = await tx.wait();
console.log("Done!", receipt);
Important Transaction Fields
| Field | Purpose | Example |
|---|---|---|
| nonce | Prevents replay | 42 |
| gasPrice | How much per unit | 20 gwei |
| gasLimit | Maximum fuel | 21000 |
| to | Destination | 0x123… |
| value | ETH amount | 1 ETH |
| data | Function call | 0xa9059… |
📝 Events and Logs: Your Robot’s Diary
Why Events Matter
Events are like your robot writing in a diary. Later, anyone can read what happened without checking every transaction!
Declaring an Event
event Transfer(
address indexed from,
address indexed to,
uint256 amount
);
The word indexed means “make it searchable!” — like adding a bookmark.
Emitting an Event
function transfer(address to, uint256 amt)
public {
balances[msg.sender] -= amt;
balances[to] += amt;
emit Transfer(msg.sender, to, amt);
}
Reading Events
// Find all transfers TO Alice
const filter = contract.filters
.Transfer(null, "0xAlice");
const events = await contract
.queryFilter(filter);
Why Use Events?
| Without Events | With Events |
|---|---|
| Check every block 😩 | Search instantly ⚡ |
| Very expensive | Very cheap |
| Slow and painful | Fast and easy |
⛽ Gas Optimization: Making Your Robot Efficient
What is Gas?
Gas is the fuel your transaction needs to run. Less gas = cheaper transactions = happy users!
Easy Wins for Gas Savings
1. Use Smaller Data Types
// ❌ Expensive
uint256 age;
// ✅ Cheaper (if value fits)
uint8 age; // Max 255
2. Pack Your Variables
// ❌ Uses 3 storage slots
uint256 a;
uint8 b;
uint256 c;
// ✅ Uses 2 storage slots
uint256 a;
uint256 c;
uint8 b;
3. Use Memory vs Storage Wisely
// ❌ Reads from storage many times
function bad() public view {
for(uint i=0; i<arr.length; i++) {
// arr.length reads storage!
}
}
// ✅ Cache in memory
function good() public view {
uint len = arr.length;
for(uint i=0; i<len; i++) {
// len is in memory
}
}
4. Short-Circuit Conditions
// ✅ Cheap check first
if (simpleCheck && expensiveCheck) {
// If simpleCheck fails,
// expensiveCheck never runs!
}
Gas Cost Reference
| Operation | Gas Cost |
|---|---|
| Add numbers | 3 |
| Store new value | 20,000 |
| Change stored value | 5,000 |
| Read storage | 200 |
| Create contract | 32,000+ |
🔄 Contract Upgradability: Teaching Old Robots New Tricks
The Problem
Smart contracts are permanent. Once deployed, the code cannot change. But what if you find a bug? Or want new features?
The Solution: Separate Logic from Storage
Think of it like this:
- Storage: Your robot’s brain (memories, data)
- Logic: Your robot’s instructions (what to do)
Keep them separate so you can update instructions without losing memories!
Upgrade Pattern Overview
graph TD A["User"] --> B["Proxy Contract"] B -->|Stores Data| C["Storage"] B -->|Delegates Calls| D["Logic V1"] D -.->|Upgrade| E["Logic V2"]
Important Rules
-
Storage layout must stay same — New version can add variables, but never remove or reorder existing ones
-
Use initializers, not constructors — Constructors don’t work with proxies!
// ❌ Won't work with proxy
constructor() {
owner = msg.sender;
}
// ✅ Works with proxy
function initialize() public {
require(!initialized);
owner = msg.sender;
initialized = true;
}
🎭 Proxy Patterns: The Robot’s Stunt Double
What’s a Proxy?
A proxy is like a stunt double in movies. The proxy stands in front, receives all commands, but secretly passes them to the real actor (implementation contract) behind the scenes!
How Delegatecall Works
graph LR A["User"] -->|Call| B["Proxy"] B -->|delegatecall| C["Implementation"] C -->|Uses Proxy's Storage| B
The magic: Code runs from Implementation, but storage is in Proxy!
Common Proxy Types
1. Transparent Proxy
Admin → can upgrade
Users → can use functions
The proxy checks: “Are you admin? Then upgrade. Are you user? Then use the contract.”
2. UUPS Proxy
Upgrade logic lives IN the
implementation contract itself
Simpler proxy, upgrade function is part of the logic contract.
3. Beacon Proxy
Multiple proxies → One beacon
Beacon points to → Implementation
Change the beacon, and ALL proxies update at once!
Simple Proxy Example
contract Proxy {
address public implementation;
fallback() external payable {
address impl = implementation;
assembly {
calldatacopy(0, 0, calldatasize())
let result := delegatecall(
gas(), impl, 0,
calldatasize(), 0, 0
)
returndatacopy(0, 0, returndatasize())
switch result
case 0 { revert(0, returndatasize()) }
default { return(0, returndatasize()) }
}
}
}
🏭 Factory Patterns: Building Robot Factories
What’s a Factory?
Instead of building one robot at a time, build a factory that can create many robots! Each robot is a new contract.
Why Use Factories?
- Consistency: Every created contract follows the same template
- Tracking: Factory knows all contracts it created
- Efficiency: One deployment creates a factory for unlimited contracts
Simple Factory Example
contract RobotFactory {
Robot[] public robots;
function createRobot(string memory name)
public returns (address) {
Robot newRobot = new Robot(name);
robots.push(newRobot);
return address(newRobot);
}
function getRobotCount()
public view returns (uint) {
return robots.length;
}
}
Clone Factory (Cheaper!)
Creating full contracts is expensive. Clones are cheaper copies that delegate to a master!
// Uses EIP-1167 minimal proxy
function createClone(address master)
internal returns (address clone) {
// Creates tiny proxy pointing
// to master implementation
}
Factory Pattern Comparison
| Type | Gas Cost | Flexibility |
|---|---|---|
| Full Deploy | High (~500k+) | Full |
| Clone/Minimal | Low (~45k) | Shared logic |
| Create2 Factory | Medium | Predictable address |
Create2: Predictable Addresses
With CREATE2, you can know the address before deploying!
address predicted = address(uint160(
uint(keccak256(abi.encodePacked(
bytes1(0xff),
factoryAddress,
salt,
keccak256(bytecode)
)))
));
This is useful for:
- Counterfactual deployments
- Cross-chain deployments
- Pre-computing addresses for approvals
🎯 Quick Summary
| Concept | What It Does | Remember As |
|---|---|---|
| ABI | Translation book | Remote control manual |
| Function Calls | Commands to contract | Talking to your robot |
| Transactions | Sealed envelopes | Missions with fuel |
| Events/Logs | Searchable diary | Robot’s journal |
| Gas Optimization | Save money | Efficiency training |
| Upgradability | Update logic safely | Teaching new tricks |
| Proxy Patterns | Stunt double | Stand-in actor |
| Factory Patterns | Create many | Robot assembly line |
🚀 You Did It!
You now understand the core building blocks of professional smart contract development!
Remember:
- ABI helps apps talk to contracts
- Functions can read (free) or write (costs gas)
- Transactions carry your commands
- Events create searchable history
- Gas optimization saves money
- Proxies enable upgrades
- Factories create multiple contracts
Go build something amazing! 🌟
