Contract Development

Back

Loading concept...

🏗️ 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:

  1. Your instruction: “Send 10 tokens to Alice”
  2. ABI encodes it: 0xa9059cbb000000...
  3. Network processes: Miners/validators run the code
  4. 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

  1. Storage layout must stay same — New version can add variables, but never remove or reorder existing ones

  2. 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! 🌟

Loading story...

Story - Premium Content

Please sign in to view this story and start learning.

Upgrade to Premium to unlock full access to all stories.

Stay Tuned!

Story is coming soon.

Story Preview

Story - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.