Back to Blog

Web3 and Blockchain Development: Smart Contracts, DeFi, and Practical Use Cases

Build real blockchain applications — Solidity smart contracts, ERC-20 tokens, DeFi protocols, NFT contracts, and Web3 frontends with ethers.js. Includes cost es

Viprasol Tech Team
April 15, 2026
13 min read

Web3 and Blockchain Development: Smart Contracts, DeFi, and Practical Use Cases

The blockchain hype cycle has completed a full rotation since 2021. What's left after the NFT mania and DeFi summer is a clearer picture of where blockchain actually adds value — and a set of mature developer tools that make building production-grade Web3 applications tractable.

This guide covers the real use cases with working code, not the speculative ones. Smart contracts, token systems, on-chain governance, and the Web3 frontend integration that makes it usable.


When Blockchain Is and Isn't the Answer

Before writing a single line of Solidity, evaluate whether blockchain is the right tool:

Blockchain adds value when:

  • Multiple untrusting parties need to share state
  • Immutability and auditability are core requirements
  • Eliminating intermediaries reduces cost or increases access
  • Programmable settlement (automatic payment on condition) has real value
  • Tokenized ownership or transferability is the feature

Blockchain is overkill when:

  • A single organization controls all parties (just use a database)
  • The use case is "we want an auditable database" (append-only PostgreSQL + audit log)
  • The immutability is theoretical but no one actually audits on-chain
  • The "decentralization" is marketing (single admin key controls everything)

Legitimate use cases in 2026:

  • Cross-border payment rails without banking intermediaries
  • Supply chain provenance for regulated industries
  • On-chain securities settlement (tokenized RWAs)
  • DAO governance for protocol parameter changes
  • Cross-game asset ownership for gaming
  • Permissionless lending/borrowing (DeFi protocols)

Solidity Smart Contract Fundamentals

Solidity compiles to EVM bytecode, deployable on Ethereum and any EVM-compatible chain (Polygon, Base, Arbitrum, Optimism).

ERC-20 Token with access controls:

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

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/security/Pausable.sol";

contract ViprasolToken is ERC20, Ownable, Pausable {
    uint256 public constant MAX_SUPPLY = 100_000_000 * 10**18; // 100M tokens
    
    mapping(address => bool) public blacklisted;
    
    event AddressBlacklisted(address indexed account);
    event AddressWhitelisted(address indexed account);

    constructor(address initialOwner) 
        ERC20("Viprasol Token", "VPR") 
        Ownable(initialOwner) 
    {
        // Mint initial supply to owner (treasury)
        _mint(initialOwner, 10_000_000 * 10**18); // 10M initial
    }

    function mint(address to, uint256 amount) external onlyOwner {
        require(totalSupply() + amount <= MAX_SUPPLY, "Exceeds max supply");
        _mint(to, amount);
    }

    function blacklist(address account) external onlyOwner {
        blacklisted[account] = true;
        emit AddressBlacklisted(account);
    }

    function whitelist(address account) external onlyOwner {
        blacklisted[account] = false;
        emit AddressWhitelisted(account);
    }

    function pause() external onlyOwner { _pause(); }
    function unpause() external onlyOwner { _unpause(); }

    // Override transfer to check blacklist and pause state
    function _update(address from, address to, uint256 value) 
        internal 
        override 
        whenNotPaused 
    {
        require(!blacklisted[from] && !blacklisted[to], "Address blacklisted");
        super._update(from, to, value);
    }
}

Vesting contract (common for team/investor token distribution):

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

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

contract TokenVesting {
    using SafeERC20 for IERC20;
    
    struct VestingSchedule {
        address beneficiary;
        uint256 totalAmount;
        uint256 cliffDuration;  // Seconds until first tokens unlock
        uint256 vestingDuration; // Total vesting period in seconds
        uint256 startTime;
        uint256 released;
        bool revocable;
        bool revoked;
    }
    
    IERC20 public immutable token;
    address public immutable owner;
    
    mapping(bytes32 => VestingSchedule) public vestingSchedules;
    mapping(address => uint256) public holdersVestingCount;
    
    event TokensReleased(address indexed beneficiary, uint256 amount);
    event VestingCreated(bytes32 indexed scheduleId, address indexed beneficiary, uint256 amount);
    
    constructor(address _token) {
        token = IERC20(_token);
        owner = msg.sender;
    }
    
    function createVestingSchedule(
        address beneficiary,
        uint256 amount,
        uint256 cliffDuration,
        uint256 vestingDuration,
        bool revocable
    ) external returns (bytes32) {
        require(msg.sender == owner, "Not owner");
        require(beneficiary != address(0), "Invalid beneficiary");
        require(amount > 0, "Amount must be positive");
        require(vestingDuration > 0, "Duration must be positive");
        require(vestingDuration >= cliffDuration, "Vesting < cliff");
        
        require(
            token.balanceOf(address(this)) >= amount,
            "Insufficient tokens"
        );
        
        bytes32 scheduleId = keccak256(abi.encodePacked(
            beneficiary,
            holdersVestingCount[beneficiary]
        ));
        holdersVestingCount[beneficiary]++;
        
        vestingSchedules[scheduleId] = VestingSchedule({
            beneficiary: beneficiary,
            totalAmount: amount,
            cliffDuration: cliffDuration,
            vestingDuration: vestingDuration,
            startTime: block.timestamp,
            released: 0,
            revocable: revocable,
            revoked: false
        });
        
        emit VestingCreated(scheduleId, beneficiary, amount);
        return scheduleId;
    }
    
    function computeReleasableAmount(bytes32 scheduleId) public view returns (uint256) {
        VestingSchedule storage schedule = vestingSchedules[scheduleId];
        if (schedule.revoked) return 0;
        
        uint256 elapsed = block.timestamp - schedule.startTime;
        if (elapsed < schedule.cliffDuration) return 0;
        
        uint256 vested;
        if (elapsed >= schedule.vestingDuration) {
            vested = schedule.totalAmount;
        } else {
            vested = (schedule.totalAmount * elapsed) / schedule.vestingDuration;
        }
        
        return vested - schedule.released;
    }
    
    function release(bytes32 scheduleId) external {
        VestingSchedule storage schedule = vestingSchedules[scheduleId];
        require(msg.sender == schedule.beneficiary, "Not beneficiary");
        
        uint256 releasable = computeReleasableAmount(scheduleId);
        require(releasable > 0, "No tokens releasable");
        
        schedule.released += releasable;
        token.safeTransfer(schedule.beneficiary, releasable);
        
        emit TokensReleased(schedule.beneficiary, releasable);
    }
}

🤖 Can This Strategy Be Automated?

In 2026, top traders run custom EAs — not manual charts. We build MT4/MT5 Expert Advisors that execute your exact strategy 24/7, pass prop firm challenges, and eliminate emotional decisions.

  • Runs 24/7 — no screen time, no missed entries
  • Prop-firm compliant (FTMO, MFF, TFT drawdown rules)
  • MyFXBook-verified backtest results included
  • From strategy brief to live EA in 2–4 weeks

Testing Smart Contracts with Hardhat

// test/ViprasolToken.test.ts
import { expect } from 'chai';
import { ethers } from 'hardhat';
import { loadFixture } from '@nomicfoundation/hardhat-toolbox/network-helpers';

async function deployTokenFixture() {
  const [owner, addr1, addr2] = await ethers.getSigners();
  const ViprasolToken = await ethers.getContractFactory('ViprasolToken');
  const token = await ViprasolToken.deploy(owner.address);
  return { token, owner, addr1, addr2 };
}

describe('ViprasolToken', () => {
  it('should have correct initial supply', async () => {
    const { token, owner } = await loadFixture(deployTokenFixture);
    const balance = await token.balanceOf(owner.address);
    expect(balance).to.equal(ethers.parseEther('10000000'));  // 10M
  });

  it('should not allow transfer from blacklisted address', async () => {
    const { token, owner, addr1 } = await loadFixture(deployTokenFixture);
    
    // Transfer some tokens to addr1
    await token.transfer(addr1.address, ethers.parseEther('1000'));
    
    // Blacklist addr1
    await token.blacklist(addr1.address);
    
    // Try to transfer from blacklisted address
    await expect(
      token.connect(addr1).transfer(owner.address, ethers.parseEther('100'))
    ).to.be.revertedWith('Address blacklisted');
  });

  it('should not exceed max supply', async () => {
    const { token, owner, addr1 } = await loadFixture(deployTokenFixture);
    const maxSupply = await token.MAX_SUPPLY();
    const totalSupply = await token.totalSupply();
    const remaining = maxSupply - totalSupply;
    
    // Try to mint more than remaining
    await expect(
      token.mint(addr1.address, remaining + 1n)
    ).to.be.revertedWith('Exceeds max supply');
  });
});

Web3 Frontend with ethers.js and React

// hooks/useWeb3.ts
import { useState, useEffect, useCallback } from 'react';
import { BrowserProvider, Contract, formatEther, parseEther } from 'ethers';
import ViprasolTokenABI from '@/contracts/ViprasolToken.json';

const TOKEN_ADDRESS = process.env.NEXT_PUBLIC_TOKEN_CONTRACT!;

export function useWeb3() {
  const [provider, setProvider] = useState<BrowserProvider | null>(null);
  const [address, setAddress] = useState<string | null>(null);
  const [balance, setBalance] = useState<string>('0');
  const [chainId, setChainId] = useState<number | null>(null);

  const connect = useCallback(async () => {
    if (!window.ethereum) {
      alert('Please install MetaMask');
      return;
    }

    const _provider = new BrowserProvider(window.ethereum);
    const accounts = await _provider.send('eth_requestAccounts', []);
    const network = await _provider.getNetwork();

    setProvider(_provider);
    setAddress(accounts[0]);
    setChainId(Number(network.chainId));

    // Load token balance
    const contract = new Contract(TOKEN_ADDRESS, ViprasolTokenABI, _provider);
    const rawBalance = await contract.balanceOf(accounts[0]);
    setBalance(formatEther(rawBalance));
  }, []);

  const sendToken = useCallback(async (to: string, amount: string) => {
    if (!provider || !address) throw new Error('Not connected');

    const signer = await provider.getSigner();
    const contract = new Contract(TOKEN_ADDRESS, ViprasolTokenABI, signer);

    const tx = await contract.transfer(to, parseEther(amount));
    const receipt = await tx.wait();

    return receipt.hash;
  }, [provider, address]);

  // Listen for account and network changes
  useEffect(() => {
    if (!window.ethereum) return;

    window.ethereum.on('accountsChanged', (accounts: string[]) => {
      setAddress(accounts[0] ?? null);
    });

    window.ethereum.on('chainChanged', (chainId: string) => {
      setChainId(parseInt(chainId, 16));
    });

    return () => {
      window.ethereum?.removeAllListeners?.();
    };
  }, []);

  return { provider, address, balance, chainId, connect, sendToken };
}

📈 Stop Trading Manually — Let AI Do It

While you sleep, your EA keeps working. Viprasol builds prop-firm-compliant Expert Advisors with strict risk management, real backtests, and live deployment support.

  • No rule violations — daily drawdown, max drawdown, consistency rules built in
  • Covers MT4, MT5, cTrader, and Python-based algos
  • 5.0★ Upwork record — 100% job success rate
  • Free strategy consultation before we write a single line

Deployment and Gas Costs

// hardhat.config.ts
import { HardhatUserConfig } from 'hardhat/config';

const config: HardhatUserConfig = {
  solidity: {
    version: '0.8.20',
    settings: {
      optimizer: { enabled: true, runs: 200 },
    },
  },
  networks: {
    mainnet: {
      url: `https://mainnet.infura.io/v3/${process.env.INFURA_KEY}`,
      accounts: [process.env.DEPLOYER_PRIVATE_KEY!],
    },
    base: {
      url: 'https://mainnet.base.org',
      accounts: [process.env.DEPLOYER_PRIVATE_KEY!],
      chainId: 8453,
    },
    polygon: {
      url: 'https://polygon-rpc.com',
      accounts: [process.env.DEPLOYER_PRIVATE_KEY!],
    },
  },
  etherscan: {
    apiKey: {
      mainnet: process.env.ETHERSCAN_API_KEY!,
      base: process.env.BASESCAN_API_KEY!,
    },
  },
};

Gas cost estimates (April 2026, Ethereum mainnet at ~15 gwei):

OperationGas UsedETH CostUSD (~$3,200 ETH)
Deploy ERC-20~1,000,0000.015 ETH~$48
Token transfer~65,0000.001 ETH~$3
Approve spending~46,0000.0007 ETH~$2.24
Swap on Uniswap~150,0000.0023 ETH~$7.20

Layer 2 costs (Base, Arbitrum, Optimism): 10–100× cheaper. ERC-20 deploy costs ~$0.50–2 on L2. For new projects, L2 is almost always the right choice.


Smart Contract Security

The most expensive bugs in software history are Solidity vulnerabilities. Foundational security practices:

// ❌ Reentrancy vulnerability (The DAO hack — $60M in 2016)
function withdraw(uint256 amount) external {
    require(balances[msg.sender] >= amount);
    (bool success,) = msg.sender.call{value: amount}("");  // External call BEFORE state update
    require(success);
    balances[msg.sender] -= amount;  // State update AFTER — attacker re-enters above
}

// ✅ Checks-Effects-Interactions pattern
function withdraw(uint256 amount) external nonReentrant {
    require(balances[msg.sender] >= amount, "Insufficient balance");
    balances[msg.sender] -= amount;  // State update FIRST
    (bool success,) = msg.sender.call{value: amount}("");  // External call LAST
    require(success, "Transfer failed");
}

Security audit cost: $15,000–$100,000+ depending on complexity. Required before mainnet deployment of any contract holding significant value. Use Trail of Bits, OpenZeppelin, or Certik. For smaller projects, use Slither (free automated analysis) as a baseline.


Build Cost Reference

ScopeTimelineCost
ERC-20 token + vesting2–4 weeks$8,000–20,000
NFT collection (ERC-721)2–4 weeks$8,000–20,000
DeFi protocol (AMM/lending)3–6 months$100,000–500,000
Full Web3 app (frontend + contracts)6–12 weeks$40,000–120,000
Security audit2–4 weeks$15,000–100,000

Working With Viprasol

We build production Web3 applications — smart contracts, token systems, DeFi integrations, and Web3 frontends. Our development process includes automated testing, professional security reviews, and mainnet deployment support.

We're also honest about when blockchain isn't the right tool — some "blockchain projects" are better served by a traditional database with a good audit trail.

Talk to our blockchain team about your Web3 project.


See Also

Share this article:

About the Author

V

Viprasol Tech Team

Custom Software Development Specialists

The Viprasol Tech team specialises in algorithmic trading software, AI agent systems, and SaaS development. With 100+ projects delivered across MT4/MT5 EAs, fintech platforms, and production AI systems, the team brings deep technical experience to every engagement. Based in India, serving clients globally.

MT4/MT5 EA DevelopmentAI Agent SystemsSaaS DevelopmentAlgorithmic Trading

Ready to Automate Your Trading?

Get a custom Expert Advisor built by professionals with verified MyFXBook results.

Free consultation • No commitment • Response within 24 hours

Viprasol · Trading Software

Need a custom EA or trading bot built?

We specialise in MT4/MT5 Expert Advisor development — prop-firm compliant, forward-tested before live, MyFXBook verifiable. 5.0★ Upwork, 100% Job Success, 100+ projects shipped.