Back to Course

Session 3.1 - Anatomy of Smart Contracts

Defining smart contract components and structure

Module 3 45 minutes Foundation Level

Learning Objectives

By the end of this session, you will be able to:

  • Define smart contract components and structure
  • Understand the fundamental building blocks of smart contracts
  • Analyze the relationship between code, state, and execution
  • Identify different types of smart contract architectures
  • Evaluate the capabilities and limitations of smart contracts

What are Smart Contracts?

Core Definition

A smart contract is a self-executing program stored on a blockchain that automatically enforces the terms of an agreement when predetermined conditions are met, without requiring intermediaries.

Traditional Contracts
  • Written in natural language
  • Require human interpretation
  • Need legal enforcement
  • Prone to disputes and ambiguity
  • Expensive to execute and enforce
Smart Contracts
  • Written in programming code
  • Deterministic execution
  • Self-enforcing
  • Transparent and verifiable
  • Automated and cost-effective
Simple Example: Escrow Contract

Traditional: "Party A deposits $1000. When Party B delivers the goods and Party A confirms receipt, release the money to Party B."

Smart Contract: Code that holds $1000, automatically releases it to Party B when Party A calls the confirmReceipt() function.

Core Components of Smart Contracts

Contract Code

The executable logic that defines contract behavior

Elements
  • Functions: Executable methods
  • Variables: Data storage
  • Events: Notifications
  • Modifiers: Access control
Languages

Solidity, Vyper, Rust, Move

Contract State

Persistent data stored on the blockchain

Types
  • State Variables: Permanent storage
  • Local Variables: Temporary data
  • Global Variables: Blockchain info
  • Constants: Immutable values
Storage

On-chain, immutable, expensive

Execution Environment

The virtual machine that runs the contract

Features
  • Deterministic: Same input = same output
  • Isolated: Sandboxed execution
  • Gas-metered: Resource limitations
  • Verifiable: Transparent execution
Examples

EVM, WASM, Move VM

Anatomy of an Ethereum Smart Contract — Block Diagram

External Callers
  • dApp Frontend (JSON-RPC)
  • EOA / Wallet (MetaMask, HW wallet)
  • Other Contracts (internal msg)
  • Off-chain services (oracles)
  • Send Transaction / Call + calldata
  • value (ETH) optional
  • gas limit / max fee / signature
Pragma & Imports
  • 4-byte selector → function
  • Argument decoding (ABI)
  • calldata/code on-chain (plain ETH)
Modifiers / Guards
  • access control (onlyOwner, roles)
  • reentrancy, pausability, checks-effects-interactions
Functions
External/Public
  • payable
  • view
  • pure (ETH)
  • emit events
Internal/Private
  • library calls
  • helper functions
  • validation
State & Memory Layout
  • storage (persistent): mappings, arrays, structs, slots, packed vars
  • memory (per-call): function locals, arrays
  • calldata (read-only args)
  • events: topic + data (external filter)
  • errors/custom errors for efficient reverts
  • inheritance & layout order matter
Libraries & Using For
  • linked or internal
  • math/string utils
Inheritance / Interfaces
  • virtual/override
  • IERC20/IERC721 etc
Constructor / receive() / fallback()
  • one-time init, ETH reception, catch-all
Return Values & Events (Logs)
  • ABI-encoded data
  • emit Event(...) → indexed topics for indexing
EVM Execution & Gas
  • opcode execution, gas metering (RPC)
  • revert/return semantics
  • delegatecall/call/staticcall
  • tx.origin vs msg.sender (avoid tx.origin)
Blockchain State & Logs
  • state trie (accounts/storage)
  • receipt logs (events) + bloom
  • block context (timestamp, number)
  • chainid, gas price/basefee
Execution Flow

Flow: calldata → selector dispatch → modifiers → function → state update → events/return → receipts

Key concerns: visibility, access control, reentrancy, gas efficiency, storage layout, ABI compatibility

Anatomy of an Ethereum Smart Contract

An Ethereum smart contract is a program deployed on the blockchain that runs on the Ethereum Virtual Machine (EVM). Its anatomy can be understood in layers:

  1. External Callers
    • Who interacts?
      • Users (wallets like MetaMask, Ledger, Coinbase Wallet)
      • dApps/frontends (via JSON-RPC)
      • Other contracts (internal calls)
      • Oracles/off-chain services
    • What do they send?
      • Transaction or call with:
        • calldata (encoded function + args)
        • optional value (ETH)
        • gas limit & fee
        • signature (for EOAs)
  2. ABI & Function Dispatcher
    • First 4 bytes of calldata = function selector (determines which function to run)
    • If no match:
      • fallback() runs for unmatched calls
      • receive() runs for plain ETH transfers
    • ABI (Application Binary Interface) defines input/output encoding
  3. Modifiers & Guards
    • Extra checks before function logic
    • Examples:
      • onlyOwner / onlyRole – restrict access
      • nonReentrant – block reentrancy attacks
      • whenNotPaused – pause/unpause features
    • Follows checks–effects–interactions pattern
  4. Functions
    • External/Public: callable by anyone (payable, view, pure)
    • Internal/Private: helpers, used inside contract/libraries
    • May emit events or return values
  5. State & Memory Layout
    • Storage: Persistent, costly (e.g., balances, mappings, arrays)
    • Memory: Temporary, per-call (function-local variables, arrays)
    • Calldata: Read-only input args
    • Events: Emitted for off-chain indexing (e.g., Transfer in ERC-20)
    • Errors/Custom Errors: Efficient revert messages
  6. Libraries & Inheritance
    • Libraries: Shared, reusable code (e.g., SafeMath)
    • Inheritance/Interfaces: OOP-like code reuse (e.g., ERC20 is Context, IERC20, Ownable)
  7. Constructor / Special Functions
    • constructor: Runs once on deployment, sets initial state
    • receive(): Handles plain ETH transfers
    • fallback(): Catch-all for unexpected calls or proxy forwarding
  8. Return Values & Events
    • Functions can return ABI-encoded data
    • emit Event(...) logs stored in transaction receipts, indexed via topics
  9. EVM Execution & Gas
    • Contract runs as bytecode on the EVM
    • Every operation consumes gas
    • If gas runs out, transaction reverts
    • Supports advanced calls: delegatecall, staticcall, call
  10. Blockchain State & Context
    • Contract interacts with:
      • Account model (balance, nonce, storage root)
      • Block context (timestamp, block number, chain ID, base fee)
      • Logs (Bloom filters) for searching events

Smart Contract Structure

Basic Solidity Contract Structure:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract SimpleEscrow {
    // State variables
    address public buyer;
    address public seller;
    uint256 public amount;
    bool public isComplete;
    
    // Events
    event FundsDeposited(uint256 amount);
    event FundsReleased(address to, uint256 amount);
    
    // Constructor
    constructor(address _seller) {
        buyer = msg.sender;
        seller = _seller;
        isComplete = false;
    }
    
    // Functions
    function deposit() public payable {
        require(msg.sender == buyer, "Only buyer can deposit");
        require(msg.value > 0, "Must deposit some amount");
        amount = msg.value;
        emit FundsDeposited(msg.value);
    }
    
    function release() public {
        require(msg.sender == buyer, "Only buyer can release");
        require(amount > 0, "No funds to release");
        require(!isComplete, "Already completed");
        
        isComplete = true;
        payable(seller).transfer(amount);
        emit FundsReleased(seller, amount);
    }
}
Contract Declaration
  • License: SPDX identifier
  • Pragma: Compiler version
  • Contract Name: Unique identifier
  • Inheritance: Parent contracts (optional)
Contract Body
  • State Variables: Contract storage
  • Events: Logging mechanism
  • Constructor: Initialization code
  • Functions: Contract behavior

Function Types and Visibility

Visibility Description Access Use Case
public Accessible from anywhere Internal + External Main contract interface
external Only callable from outside External only API functions
internal Only within contract and derived Internal only Helper functions
private Only within current contract Current contract only Internal logic
Function Modifiers
  • view: Reads state, doesn't modify
  • pure: No state interaction
  • payable: Can receive Ether
  • nonpayable: Cannot receive Ether (default)
Custom Modifiers
modifier onlyOwner() {
    require(msg.sender == owner, "Not owner");
    _;
}

function withdraw() public onlyOwner {
    // Function body
}

Data Types and Storage

Value Types
  • bool: true/false
  • uint: Unsigned integers
  • int: Signed integers
  • address: Ethereum addresses
  • bytes: Fixed-size byte arrays
  • string: UTF-8 text
Reference Types
  • arrays: Dynamic or fixed-size
  • structs: Custom data structures
  • mappings: Key-value pairs
  • strings: Dynamic byte arrays
  • bytes: Dynamic byte arrays
Storage Locations
  • storage: Persistent blockchain storage
  • memory: Temporary execution memory
  • calldata: Read-only function parameters
  • stack: Local variables (automatic)
Data Structure Example
struct User {
    string name;
    uint256 balance;
    bool isActive;
}

mapping(address => User) public users;
uint256[] public balances;
address[] public userAddresses;

Contract Lifecycle

1. Development

Write and test contract code

2. Deployment

Deploy to blockchain network

3. Execution

Users interact with contract

4. Termination

Contract becomes inactive

Immutability Consideration

Once deployed, smart contracts are typically immutable. This means:

  • Code cannot be changed after deployment
  • Bugs cannot be easily fixed
  • Upgradability must be designed from the beginning
  • Thorough testing is crucial before deployment

Common Contract Patterns

Access Control

Restrict function access to authorized users

address public owner;

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

Emergency stop mechanism for critical situations

bool public stopped = false;

modifier stopInEmergency() {
    require(!stopped);
    _;
}
Withdrawal Pattern

Safe way to handle Ether transfers

mapping(address => uint) pendingWithdrawals;

function withdraw() public {
    uint amount = pendingWithdrawals[msg.sender];
    pendingWithdrawals[msg.sender] = 0;
    payable(msg.sender).transfer(amount);
}
State Machine

Manage contract states and transitions

enum State { Created, Locked, Released }
State public state;

modifier inState(State _state) {
    require(state == _state);
    _;
}

Session Summary

Key Takeaways
  • Smart contracts are self-executing programs that automate agreement enforcement
  • Core components include contract code, state variables, and execution environment
  • Contract structure follows specific patterns with functions, modifiers, and events
  • Function visibility and modifiers control access and behavior
  • Data types and storage locations affect gas costs and functionality
  • Contract lifecycle includes development, deployment, execution, and termination
  • Common patterns solve recurring problems in smart contract development

What's Next?

In the next session, we'll explore the Life Cycle of smart contracts, tracing their journey from development through deployment and execution, including upgrade patterns and termination strategies.