Blockchain Basics: A Developer's Guide to Distributed Ledger Technology

Blockchain Basics: A Developer's Guide to Distributed Ledger Technology

Master the fundamentals of blockchain technology, smart contracts, and decentralized applications. Learn how to build secure and scalable blockchain solutions with practical examples and best practices.

Michael Chen
Michael Chen
Blockchain Developer
February 15, 2024
16 min read
Blockchain Smart Contracts Web3 Ethereum Solidity DeFi Cryptocurrency

Introduction

Blockchain technology has revolutionized how we think about trust, transparency, and decentralization in digital systems. This comprehensive guide explores the fundamental concepts and practical implementations of blockchain technology.

1. Smart Contract Development

Smart contracts are self-executing contracts with terms directly written into code. Let’s explore their implementation.

Basic Smart Contract

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract TokenVesting {
    struct VestingSchedule {
        uint256 totalAmount;
        uint256 releasedAmount;
        uint256 startTime;
        uint256 duration;
        uint256 cliff;
    }

    mapping(address => VestingSchedule) public vestingSchedules;
    address public immutable token;
    
    event TokensVested(address indexed beneficiary, uint256 amount);
    event VestingScheduleCreated(address indexed beneficiary, uint256 amount);

    constructor(address _token) {
        require(_token != address(0), "Invalid token address");
        token = _token;
    }

    function createVestingSchedule(
        address _beneficiary,
        uint256 _totalAmount,
        uint256 _startTime,
        uint256 _duration,
        uint256 _cliff
    ) external {
        require(_beneficiary != address(0), "Invalid beneficiary");
        require(_totalAmount > 0, "Amount must be > 0");
        require(_duration > 0, "Duration must be > 0");
        require(_cliff <= _duration, "Cliff must be <= duration");

        VestingSchedule storage schedule = vestingSchedules[_beneficiary];
        require(schedule.totalAmount == 0, "Schedule already exists");

        schedule.totalAmount = _totalAmount;
        schedule.startTime = _startTime;
        schedule.duration = _duration;
        schedule.cliff = _cliff;

        emit VestingScheduleCreated(_beneficiary, _totalAmount);
    }

    function release() external {
        VestingSchedule storage schedule = vestingSchedules[msg.sender];
        require(schedule.totalAmount > 0, "No vesting schedule");
        
        uint256 releasable = _getReleasableAmount(schedule);
        require(releasable > 0, "No tokens to release");

        schedule.releasedAmount += releasable;
        emit TokensVested(msg.sender, releasable);

        require(
            IERC20(token).transfer(msg.sender, releasable),
            "Transfer failed"
        );
    }

    function _getReleasableAmount(
        VestingSchedule memory schedule
    ) private view returns (uint256) {
        if (block.timestamp < schedule.startTime + schedule.cliff) {
            return 0;
        }

        if (block.timestamp >= schedule.startTime + schedule.duration) {
            return schedule.totalAmount - schedule.releasedAmount;
        }

        uint256 timeFromStart = block.timestamp - schedule.startTime;
        uint256 vestedAmount = (schedule.totalAmount * timeFromStart) / 
                              schedule.duration;
        
        return vestedAmount - schedule.releasedAmount;
    }
}

2. Web3 Integration

Frontend Integration

// Example of Web3 Integration with React
import { ethers } from 'ethers';
import { useState, useEffect } from 'react';

interface Web3State {
  provider: ethers.providers.Web3Provider | null;
  signer: ethers.Signer | null;
  address: string | null;
  chainId: number | null;
}

export function useWeb3(): Web3State {
  const [web3State, setWeb3State] = useState<Web3State>({
    provider: null,
    signer: null,
    address: null,
    chainId: null
  });

  useEffect(() => {
    async function initializeWeb3() {
      if (typeof window.ethereum !== 'undefined') {
        try {
          // Request account access
          await window.ethereum.request({ 
            method: 'eth_requestAccounts' 
          });

          const provider = new ethers.providers.Web3Provider(window.ethereum);
          const signer = provider.getSigner();
          const address = await signer.getAddress();
          const network = await provider.getNetwork();

          setWeb3State({
            provider,
            signer,
            address,
            chainId: network.chainId
          });

          // Listen for account changes
          window.ethereum.on('accountsChanged', (accounts: string[]) => {
            if (accounts.length > 0) {
              setWeb3State(prev => ({
                ...prev,
                address: accounts[0]
              }));
            } else {
              setWeb3State({
                provider: null,
                signer: null,
                address: null,
                chainId: null
              });
            }
          });

          // Listen for chain changes
          window.ethereum.on('chainChanged', (chainId: string) => {
            window.location.reload();
          });
        } catch (error) {
          console.error('Error initializing web3:', error);
        }
      }
    }

    initializeWeb3();
  }, []);

  return web3State;
}

3. Blockchain Security

Security Best Practices

// Example of Secure Smart Contract Implementation
contract SecureToken {
    using SafeMath for uint256;
    
    mapping(address => uint256) private _balances;
    mapping(address => mapping(address => uint256)) private _allowances;
    
    uint256 private _totalSupply;
    
    // Reentrancy Guard
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;
    uint256 private _status;
    
    modifier nonReentrant() {
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
        _status = _ENTERED;
        _;
        _status = _NOT_ENTERED;
    }
    
    // Events
    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(
        address indexed owner, 
        address indexed spender, 
        uint256 value
    );
    
    constructor() {
        _status = _NOT_ENTERED;
    }
    
    function transfer(
        address recipient, 
        uint256 amount
    ) public nonReentrant returns (bool) {
        require(recipient != address(0), "Invalid recipient");
        require(_balances[msg.sender] >= amount, "Insufficient balance");
        
        _balances[msg.sender] = _balances[msg.sender].sub(amount);
        _balances[recipient] = _balances[recipient].add(amount);
        
        emit Transfer(msg.sender, recipient, amount);
        return true;
    }
}

4. Decentralized Storage

IPFS Integration

// Example of IPFS Integration
import { create, IPFSHTTPClient } from 'ipfs-http-client';

interface IPFSConfig {
  host: string;
  port: number;
  protocol: string;
}

class IPFSManager {
  private ipfs: IPFSHTTPClient;

  constructor(config: IPFSConfig) {
    this.ipfs = create({
      host: config.host,
      port: config.port,
      protocol: config.protocol
    });
  }

  async uploadFile(file: File): Promise<string> {
    try {
      const added = await this.ipfs.add(file);
      return added.path;
    } catch (error) {
      throw new Error(`IPFS upload failed: ${error.message}`);
    }
  }

  async uploadJSON(data: any): Promise<string> {
    try {
      const jsonString = JSON.stringify(data);
      const added = await this.ipfs.add(jsonString);
      return added.path;
    } catch (error) {
      throw new Error(`IPFS JSON upload failed: ${error.message}`);
    }
  }

  getIPFSUrl(hash: string): string {
    return `https://ipfs.io/ipfs/${hash}`;
  }
}

5. Gas Optimization

Efficient Smart Contract Design

// Example of Gas-Optimized Contract
contract GasOptimized {
    // Use bytes32 instead of string where possible
    mapping(bytes32 => uint256) private _data;
    
    // Pack variables to use fewer storage slots
    struct UserInfo {
        uint128 balance;    // Packs into single slot
        uint64 lastUpdate;  // with these
        uint64 expiration;  // variables
    }
    
    mapping(address => UserInfo) private _userInfo;
    
    // Use events for cheap storage
    event DataUpdated(bytes32 indexed key, uint256 value);
    
    // Batch operations
    function batchUpdate(
        bytes32[] calldata keys,
        uint256[] calldata values
    ) external {
        require(keys.length == values.length, "Length mismatch");
        
        for (uint256 i = 0; i < keys.length; i++) {
            _data[keys[i]] = values[i];
            emit DataUpdated(keys[i], values[i]);
        }
    }
    
    // Use unchecked for gas optimization when safe
    function sumArray(uint256[] calldata arr) public pure returns (uint256) {
        uint256 sum = 0;
        uint256 len = arr.length;
        
        unchecked {
            for (uint256 i = 0; i < len; i++) {
                sum += arr[i];
            }
        }
        
        return sum;
    }
}

Conclusion

Blockchain technology continues to evolve and mature, offering new possibilities for building decentralized applications. Understanding these fundamentals is crucial for developing secure and efficient blockchain solutions.

Key Takeaways

  1. Smart contract security is paramount
  2. Proper Web3 integration enhances user experience
  3. Gas optimization is crucial for cost-effectiveness
  4. Decentralized storage solutions complement blockchain applications
  5. Always follow blockchain security best practices

Additional Resources