Contract Patterns

Back

Loading concept...

Smart Contract Patterns: The Building Blocks of Blockchain Magic 🏗️

Imagine you’re building with LEGO blocks. Each block has a special purpose. Some blocks are just for looking. Some blocks need coins to work. Some blocks catch things when they fall. Let’s discover all the amazing patterns that make smart contracts powerful!


The Big Picture: What Are Contract Patterns?

Think of a smart contract like a magical vending machine. It has different parts that do different jobs:

  • Some parts just show you the snacks (View functions)
  • Some parts need your coins (Payable functions)
  • Some parts catch coins that fall randomly (Fallback functions)
  • Some parts are security guards (Modifiers)
  • Some parts inherit superpowers from parent machines (Inheritance)
  • Some parts follow a rulebook (Interfaces)
  • Some parts share tools with other machines (Libraries)
  • Every machine has a unique address (Contract Address Derivation)

1. View Functions: The Window Shoppers đź‘€

What is a View Function?

A view function is like looking through a store window. You can SEE everything inside, but you can’t touch or change anything. And best of all? It’s FREE! No gas needed.

Simple Example

contract PiggyBank {
    uint public savings = 100;

    // VIEW: Just looking, not touching
    function checkBalance()
        public view returns (uint)
    {
        return savings;
    }
}

Why It’s Special

Feature View Function Regular Function
Reads data âś… Yes âś… Yes
Changes data ❌ No ✅ Yes
Costs gas ❌ Free! ⛽ Yes

Real-World Analogy

Like checking your piggy bank without opening it. You can shake it, peek through the slot, count the sounds—but you don’t add or remove any coins.

graph TD A["You"] -->|"checkBalance#40;#41;"| B["Contract"] B -->|"Returns: 100"| A C["No Gas Needed!"] --> B

2. Payable Functions: The Cash Registers đź’°

What is a Payable Function?

A payable function is like a piggy bank slot. It can receive money (ETH). Without the payable keyword, the contract will reject any money you send!

Simple Example

contract PiggyBank {
    // PAYABLE: Can receive money
    function deposit()
        public payable
    {
        // ETH automatically added to
        // contract balance
    }

    function getBalance()
        public view returns (uint)
    {
        return address(this).balance;
    }
}

The Magic Word

If you forget payable, sending ETH will fail:

// ❌ This REJECTS money
function broken() public { }

// âś… This ACCEPTS money
function working() public payable { }

Real-World Analogy

A payable function is like a vending machine’s coin slot. No slot = no way to insert coins!


3. Fallback Functions: The Safety Nets 🪢

What is a Fallback Function?

When someone sends ETH or calls a function that doesn’t exist, the fallback function catches it—like a safety net for a trapeze artist!

Two Types

There are TWO special functions:

contract SafetyNet {
    // Catches ETH with no data
    receive() external payable {
        // Someone sent ETH directly
    }

    // Catches everything else
    fallback() external payable {
        // Unknown function called OR
        // ETH sent with data
    }
}

The Decision Tree

graph TD A["ETH Received"] --> B{Has Data?} B -->|No| C{receive exists?} C -->|Yes| D["receive"] C -->|No| E["fallback"] B -->|Yes| E

Simple Example

contract CatchAll {
    event Received(
        address sender,
        uint amount
    );

    receive() external payable {
        emit Received(
            msg.sender,
            msg.value
        );
    }

    fallback() external payable {
        // Handle unknown calls
    }
}

4. Modifier Patterns: The Security Guards 🛡️

What is a Modifier?

A modifier is like a security guard at a door. Before you enter the room (run the function), the guard checks if you’re allowed!

Simple Example

contract SecureVault {
    address public owner;

    modifier onlyOwner() {
        require(
            msg.sender == owner,
            "Not the owner!"
        );
        _; // Continue to function
    }

    function openVault()
        public onlyOwner
    {
        // Only owner gets here
    }
}

Common Patterns

// Check if caller is owner
modifier onlyOwner() {
    require(msg.sender == owner);
    _;
}

// Check if not paused
modifier whenNotPaused() {
    require(!paused);
    _;
}

// Check minimum payment
modifier costs(uint price) {
    require(msg.value >= price);
    _;
}

The Underscore Magic

The _; symbol is WHERE the function code runs:

graph TD A["Call Function"] --> B["Run Modifier Code"] B --> C{Checks Pass?} C -->|Yes| D["_ runs function"] C -->|No| E["Transaction Reverts"]

5. Inheritance: Family Superpowers 👨‍👩‍👧

What is Inheritance?

Like a child inheriting traits from parents! A contract can inherit functions and variables from another contract using is.

Simple Example

// Parent contract
contract Animal {
    function speak() public pure
        virtual returns (string memory)
    {
        return "...";
    }
}

// Child inherits from Animal
contract Dog is Animal {
    function speak() public pure
        override returns (string memory)
    {
        return "Woof!";
    }
}

Key Words

Keyword Meaning
is Inherit from
virtual Can be overridden
override Replaces parent

Multiple Inheritance

contract SuperDog is Animal, Pet {
    // Has powers from BOTH!
}
graph TD A["Animal"] --> C["SuperDog"] B["Pet"] --> C

6. Interface Contracts: The Rule Books 📜

What is an Interface?

An interface is like a job description. It lists WHAT functions must exist, but not HOW they work. Any contract that follows the interface MUST implement all functions!

Simple Example

// The rulebook (interface)
interface IGreeter {
    function greet()
        external view returns (string memory);
}

// Following the rules
contract HelloWorld is IGreeter {
    function greet()
        external pure returns (string memory)
    {
        return "Hello!";
    }
}

Interface Rules

âś… Only function signatures
❌ No function bodies
❌ No state variables
❌ No constructors
âś… All functions are external

Why Use Interfaces?

graph TD A["Interface IToken"] --> B["TokenA"] A --> C["TokenB"] A --> D["TokenC"] E["Your Contract"] -->|"Works with ANY"| A

Different tokens, same interface = your code works with ALL of them!


7. Library Contracts: The Shared Toolbox đź§°

What is a Library?

A library is like a shared toolbox that many contracts can use. It contains reusable functions that don’t need their own storage.

Simple Example

// The toolbox
library Math {
    function add(uint a, uint b)
        internal pure returns (uint)
    {
        return a + b;
    }
}

// Using the toolbox
contract Calculator {
    using Math for uint;

    function calculate() public pure
        returns (uint)
    {
        uint x = 5;
        return x.add(3); // Returns 8
    }
}

Library vs Contract

Feature Library Contract
Storage ❌ None ✅ Has own
ETH ❌ Can’t hold ✅ Can hold
Inherit ❌ No ✅ Yes
Deploy Once, share Each instance

The using Magic

using Math for uint;

// Now ALL uints have .add()!
uint result = (5).add(3);

8. Contract Address Derivation: The Unique Address 📍

How Addresses Are Born

Every contract has a unique address. But HOW is it created? Two methods:

Method 1: CREATE (Normal Deployment)

Address = keccak256(
    deployer_address + nonce
)

The address depends on WHO deploys and HOW MANY times they’ve deployed before.

// Each deployment = new address
// because nonce increases
Contract1 → 0xABC...
Contract2 → 0xDEF...

Method 2: CREATE2 (Predictable)

Address = keccak256(
    0xFF +
    deployer +
    salt +
    bytecode_hash
)

Same inputs = SAME address every time!

Simple Example

contract Factory {
    function deploy(bytes32 salt)
        public returns (address)
    {
        Child c = new Child{salt: salt}();
        return address(c);
    }
}

Why CREATE2 Matters

graph TD A["Know Address BEFORE Deploy"] --> B["Users Can Send ETH"] B --> C["Contract Deploys Later"] C --> D["Collects the ETH!"]

Putting It All Together 🎯

Here’s a complete contract using ALL patterns:

// Interface (rulebook)
interface IVault {
    function deposit() external payable;
    function withdraw() external;
}

// Library (shared tools)
library SafeMath {
    function add(uint a, uint b)
        internal pure returns (uint)
    {
        return a + b;
    }
}

// Base contract (parent)
contract Ownable {
    address public owner;

    constructor() {
        owner = msg.sender;
    }

    modifier onlyOwner() {
        require(msg.sender == owner);
        _;
    }
}

// Main contract
contract Vault is Ownable, IVault {
    using SafeMath for uint;

    // View function
    function getBalance()
        public view returns (uint)
    {
        return address(this).balance;
    }

    // Payable function
    function deposit()
        external payable override
    {}

    // Modifier protected
    function withdraw()
        external override onlyOwner
    {
        payable(owner).transfer(
            address(this).balance
        );
    }

    // Fallback functions
    receive() external payable {}
    fallback() external payable {}
}

Quick Reference Table

Pattern Purpose Keyword
View Read-only, free view
Payable Accept ETH payable
Fallback Catch unknown fallback()
Receive Catch plain ETH receive()
Modifier Pre-check rules modifier
Inheritance Get parent powers is
Interface Define rules interface
Library Share tools library
CREATE2 Predict address salt

You Did It! 🎉

You now understand the 8 essential patterns of smart contracts:

  1. View functions - Free peeking
  2. Payable functions - Accept money
  3. Fallback functions - Safety nets
  4. Modifiers - Security guards
  5. Inheritance - Family superpowers
  6. Interfaces - Rule books
  7. Libraries - Shared toolboxes
  8. Address derivation - Unique locations

These patterns are the LEGO blocks of blockchain development. Mix and match them to build anything you can imagine!

Remember: Every smart contract you see uses these patterns. Now YOU know their secrets!

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.