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
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):
| Operation | Gas Used | ETH Cost | USD (~$3,200 ETH) |
|---|---|---|---|
| Deploy ERC-20 | ~1,000,000 | 0.015 ETH | ~$48 |
| Token transfer | ~65,000 | 0.001 ETH | ~$3 |
| Approve spending | ~46,000 | 0.0007 ETH | ~$2.24 |
| Swap on Uniswap | ~150,000 | 0.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
| Scope | Timeline | Cost |
|---|---|---|
| ERC-20 token + vesting | 2–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 audit | 2–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
- Fintech Compliance Software — regulatory considerations for token projects
- API Security Best Practices — securing Web3 backend APIs
- TypeScript Advanced Patterns — type-safe Web3 integration
- Software Testing Strategies — testing smart contracts
- Trading Software Development — financial application development
About the Author
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.
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
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.