Chapter 4: Introduction to Mainstream Virtual Currencies

Haiyue
30min

Chapter 4: Introduction to Mainstream Virtual Currencies

Learning Objectives
  • Understand Ethereum and smart contracts
  • Learn about other mainstream coins (Ripple, Litecoin, etc.)
  • Understand the characteristics and application scenarios of different virtual currencies
  • Master the difference between tokens and native coins

Ethereum

Basic Concepts and Features

Ethereum is a decentralized platform created by Vitalik Buterin in 2015 that supports smart contracts and decentralized applications (DApps).

Ethereum Core Features
  • Turing Complete: Supports complex programming logic
  • Smart Contracts: Self-executing code contracts
  • Virtual Machine: Ethereum Virtual Machine (EVM) execution environment
  • Gas Mechanism: Computational resource pricing system
  • Account Model: State management different from Bitcoin’s UTXO model

Smart Contract Implementation

import json
import hashlib
from typing import Dict, Any, List, Optional
from dataclasses import dataclass, field

@dataclass
class Account:
    """Ethereum account"""
    address: str
    balance: float = 0.0
    nonce: int = 0
    code: str = ""  # Contract code
    storage: Dict[str, Any] = field(default_factory=dict)  # Contract storage

class EthereumVirtualMachine:
    """Ethereum Virtual Machine (simplified version)"""

    def __init__(self):
        self.accounts: Dict[str, Account] = {}
        self.gas_price = 20  # Gwei
        self.block_gas_limit = 30_000_000

    def create_account(self, address: str, initial_balance: float = 0.0):
        """Create account"""
        self.accounts[address] = Account(address, initial_balance)

    def deploy_contract(self, deployer: str, contract_code: str,
                       constructor_args: List = None, gas_limit: int = 500_000):
        """Deploy smart contract"""
        if deployer not in self.accounts:
            raise ValueError("Deployer account does not exist")

        # Generate contract address
        deployer_account = self.accounts[deployer]
        contract_address = self._generate_contract_address(deployer, deployer_account.nonce)

        # Create contract account
        contract_account = Account(
            address=contract_address,
            balance=0.0,
            code=contract_code
        )

        # Execute constructor
        if constructor_args:
            gas_used = self._execute_constructor(contract_account, constructor_args)
        else:
            gas_used = 21000  # Base gas consumption

        # Calculate gas fee
        gas_fee = (gas_used * self.gas_price) / 1e9  # Convert to ETH

        if self.accounts[deployer].balance < gas_fee:
            raise ValueError("Insufficient balance to pay gas fee")

        # Deduct gas fee
        self.accounts[deployer].balance -= gas_fee
        self.accounts[deployer].nonce += 1

        # Save contract
        self.accounts[contract_address] = contract_account

        print(f"Contract deployed successfully")
        print(f"Contract address: {contract_address}")
        print(f"Gas consumed: {gas_used:,}")
        print(f"Gas fee: {gas_fee:.6f} ETH")

        return contract_address

    def call_contract(self, caller: str, contract_address: str,
                     function_name: str, args: List = None,
                     value: float = 0.0, gas_limit: int = 100_000):
        """Call smart contract"""
        if caller not in self.accounts or contract_address not in self.accounts:
            raise ValueError("Account or contract does not exist")

        contract = self.accounts[contract_address]
        if not contract.code:
            raise ValueError("Not a contract address")

        # Transfer ETH to contract (if any)
        if value > 0:
            if self.accounts[caller].balance < value:
                raise ValueError("Insufficient balance")
            self.accounts[caller].balance -= value
            contract.balance += value

        # Execute contract function
        gas_used = self._execute_contract_function(
            contract, function_name, args or []
        )

        # Calculate and deduct gas fee
        gas_fee = (gas_used * self.gas_price) / 1e9
        self.accounts[caller].balance -= gas_fee
        self.accounts[caller].nonce += 1

        print(f"Contract called successfully")
        print(f"Function: {function_name}")
        print(f"Gas consumed: {gas_used:,}")
        print(f"Gas fee: {gas_fee:.6f} ETH")

        return gas_used

    def _generate_contract_address(self, deployer: str, nonce: int) -> str:
        """Generate contract address"""
        # Simplified address generation: hash of deployer + nonce
        data = f"{deployer}{nonce}"
        return "0x" + hashlib.sha256(data.encode()).hexdigest()[:40]

    def _execute_constructor(self, contract: Account, args: List) -> int:
        """Execute contract constructor"""
        # Simplified implementation: base gas consumption + argument processing
        base_gas = 21000
        arg_gas = len(args) * 1000
        return base_gas + arg_gas

    def _execute_contract_function(self, contract: Account,
                                  function_name: str, args: List) -> int:
        """Execute contract function"""
        # Simplified smart contract execution simulation
        gas_costs = {
            "transfer": 21000,
            "approve": 22000,
            "mint": 25000,
            "burn": 20000,
            "get_balance": 2000,
            "set_value": 20000
        }

        base_gas = gas_costs.get(function_name, 30000)

        # Simulate different function executions
        if function_name == "transfer":
            # Transfer function
            if len(args) >= 2:
                recipient, amount = args[0], args[1]
                # Update contract storage state
                contract.storage[f"balance_{recipient}"] = \
                    contract.storage.get(f"balance_{recipient}", 0) + amount

        elif function_name == "set_value":
            # Set storage value
            if len(args) >= 2:
                key, value = args[0], args[1]
                contract.storage[key] = value

        elif function_name == "get_balance":
            # Query balance (read-only, lower gas consumption)
            pass

        return base_gas + len(args) * 500

    def get_account_info(self, address: str) -> Dict:
        """Get account information"""
        if address not in self.accounts:
            return {"error": "Account does not exist"}

        account = self.accounts[address]
        return {
            "address": account.address,
            "balance": account.balance,
            "nonce": account.nonce,
            "is_contract": bool(account.code),
            "storage_size": len(account.storage)
        }

# Ethereum smart contract demonstration
print("=== Ethereum Smart Contract Demonstration ===")

# Initialize EVM
evm = EthereumVirtualMachine()

# Create accounts
evm.create_account("0xAlice", 10.0)
evm.create_account("0xBob", 5.0)

print("Initial account state:")
print(f"Alice: {evm.get_account_info('0xAlice')}")
print(f"Bob: {evm.get_account_info('0xBob')}")

# Deploy ERC-20 token contract
token_contract_code = """
pragma solidity ^0.8.0;

contract SimpleToken {
    mapping(address => uint256) public balances;
    string public name = "SimpleToken";
    string public symbol = "SIM";
    uint256 public totalSupply;

    constructor(uint256 _totalSupply) {
        totalSupply = _totalSupply;
        balances[msg.sender] = _totalSupply;
    }

    function transfer(address _to, uint256 _amount) public {
        require(balances[msg.sender] >= _amount);
        balances[msg.sender] -= _amount;
        balances[_to] += _amount;
    }
}
"""

# Alice deploys token contract
contract_address = evm.deploy_contract(
    deployer="0xAlice",
    contract_code=token_contract_code,
    constructor_args=[1000000],  # Total supply 1 million
    gas_limit=500_000
)

# Call contract function
print(f"\n=== Token Transfer ===")
evm.call_contract(
    caller="0xAlice",
    contract_address=contract_address,
    function_name="transfer",
    args=["0xBob", 1000]  # Transfer 1000 tokens to Bob
)

print(f"\nFinal account state:")
print(f"Alice: {evm.get_account_info('0xAlice')}")
print(f"Bob: {evm.get_account_info('0xBob')}")
print(f"Token contract: {evm.get_account_info(contract_address)}")

Gas Mechanism Explained

class GasCalculator:
    """Gas fee calculator"""

    # Gas price table (simplified version)
    GAS_COSTS = {
        # Basic operations
        "ADD": 3,
        "SUB": 3,
        "MUL": 5,
        "DIV": 5,
        "SLOAD": 200,    # Read from storage
        "SSTORE": 20000, # Write to storage (new value)
        "SSTORE_UPDATE": 5000,  # Update storage
        "CALL": 700,     # External call
        "CREATE": 32000, # Create contract

        # Transaction types
        "TX_BASE": 21000,           # Base transaction
        "TX_CREATE": 53000,         # Create contract transaction
        "TX_DATA_ZERO": 4,          # Per byte zero data
        "TX_DATA_NONZERO": 16,      # Per byte non-zero data
    }

    @classmethod
    def estimate_transaction_gas(cls, tx_type: str, data_bytes: int = 0,
                                zero_bytes: int = 0) -> int:
        """Estimate transaction gas consumption"""
        base_cost = cls.GAS_COSTS.get(f"TX_{tx_type.upper()}", cls.GAS_COSTS["TX_BASE"])

        # Data cost
        nonzero_bytes = max(0, data_bytes - zero_bytes)
        data_cost = (zero_bytes * cls.GAS_COSTS["TX_DATA_ZERO"] +
                    nonzero_bytes * cls.GAS_COSTS["TX_DATA_NONZERO"])

        return base_cost + data_cost

    @classmethod
    def estimate_contract_execution(cls, operations: List[str]) -> int:
        """Estimate contract execution gas consumption"""
        total_gas = 0

        for operation in operations:
            total_gas += cls.GAS_COSTS.get(operation.upper(), 100)  # Default 100 gas

        return total_gas

    @classmethod
    def calculate_gas_fee(cls, gas_used: int, gas_price_gwei: float) -> float:
        """Calculate gas fee (ETH)"""
        return (gas_used * gas_price_gwei) / 1e9

# Gas calculation demonstration
print("\n=== Gas Fee Calculation Demonstration ===")

calc = GasCalculator()

# 1. Simple transfer
transfer_gas = calc.estimate_transaction_gas("BASE")
print(f"Simple ETH transfer gas consumption: {transfer_gas:,}")

# 2. Contract deployment
deploy_gas = calc.estimate_transaction_gas("CREATE", data_bytes=1000)
print(f"Contract deployment gas consumption: {deploy_gas:,}")

# 3. Contract function call
contract_operations = ["SLOAD", "ADD", "SSTORE", "CALL"]
execution_gas = calc.estimate_contract_execution(contract_operations)
total_gas = calc.estimate_transaction_gas("BASE") + execution_gas
print(f"Contract call gas consumption: {total_gas:,}")

# 4. Fees at different gas prices
gas_prices = [20, 50, 100, 200]  # Gwei
print(f"\nGas fee comparison (using {total_gas:,} Gas):")
for price in gas_prices:
    fee = calc.calculate_gas_fee(total_gas, price)
    print(f"  {price:3d} Gwei: {fee:.6f} ETH (${fee*2000:.2f} @ $2000/ETH)")

Other Mainstream Virtual Currencies

Ripple (XRP)

Ripple focuses on cross-border payment solutions:

import time
from typing import List
from dataclasses import dataclass

@dataclass
class RippleTransaction:
    """Ripple transaction"""
    sender: str
    receiver: str
    amount: float
    currency: str = "XRP"
    timestamp: float = None
    sequence: int = 0
    fee: float = 0.00001  # Extremely low transaction fee

    def __post_init__(self):
        if self.timestamp is None:
            self.timestamp = time.time()

class RippleLedger:
    """Ripple ledger"""

    def __init__(self):
        self.accounts: Dict[str, Dict] = {}
        self.transaction_history: List[RippleTransaction] = []
        self.validators = [
            "ripple_validator_1",
            "ripple_validator_2",
            "ripple_validator_3"
        ]

    def create_account(self, address: str, initial_balance: float = 0.0):
        """Create account (requires 20 XRP activation)"""
        if initial_balance < 20:
            raise ValueError("Ripple account requires at least 20 XRP activation")

        self.accounts[address] = {
            "balance": initial_balance,
            "sequence": 0,
            "trust_lines": {},  # Trust lines (for other currencies)
            "reserve": 20  # Account reserve
        }

    def process_payment(self, tx: RippleTransaction) -> bool:
        """Process payment transaction"""
        sender_account = self.accounts.get(tx.sender)

        if not sender_account:
            print(f"Sender account {tx.sender} does not exist")
            return False

        # Check balance (must keep reserve)
        available_balance = sender_account["balance"] - sender_account["reserve"]
        total_cost = tx.amount + tx.fee

        if available_balance < total_cost:
            print(f"Insufficient balance: available {available_balance}, needed {total_cost}")
            return False

        # Execute transaction
        sender_account["balance"] -= total_cost
        sender_account["sequence"] += 1

        # Receiver account processing
        if tx.receiver not in self.accounts:
            # Auto-create account (if amount is sufficient)
            if tx.amount >= 20:
                self.create_account(tx.receiver, tx.amount)
            else:
                print(f"Receiving amount insufficient to activate account")
                return False
        else:
            self.accounts[tx.receiver]["balance"] += tx.amount

        # Record transaction
        self.transaction_history.append(tx)

        print(f"Transaction successful: {tx.sender} -> {tx.receiver}: {tx.amount} {tx.currency}")
        return True

    def get_account_balance(self, address: str) -> Dict:
        """Get account balance"""
        account = self.accounts.get(address)
        if not account:
            return {"error": "Account does not exist"}

        return {
            "address": address,
            "balance": account["balance"],
            "available": account["balance"] - account["reserve"],
            "reserve": account["reserve"],
            "sequence": account["sequence"]
        }

# Ripple payment demonstration
print("\n=== Ripple Payment Demonstration ===")

# Initialize Ripple ledger
ripple = RippleLedger()

# Create accounts
ripple.create_account("bank_a", 1000000.0)
ripple.create_account("bank_b", 500000.0)

print("Bank account status:")
print(f"Bank A: {ripple.get_account_balance('bank_a')}")
print(f"Bank B: {ripple.get_account_balance('bank_b')}")

# Cross-border payment
cross_border_payment = RippleTransaction(
    sender="bank_a",
    receiver="bank_b",
    amount=50000.0,
    currency="XRP"
)

success = ripple.process_payment(cross_border_payment)
print(f"Cross-border payment result: {'Successful' if success else 'Failed'}")

print(f"\nAccount status after payment:")
print(f"Bank A: {ripple.get_account_balance('bank_a')}")
print(f"Bank B: {ripple.get_account_balance('bank_b')}")

# Ripple advantages display
print(f"\n=== Ripple Advantages Comparison ===")
comparison_data = {
    "Bitcoin": {"tx_time": "10-60 minutes", "fee": "$1-50", "tps": 7},
    "Ethereum": {"tx_time": "1-5 minutes", "fee": "$1-100", "tps": 15},
    "XRP": {"tx_time": "3-5 seconds", "fee": "$0.0002", "tps": 1500}
}

print("Performance comparison:")
for coin, metrics in comparison_data.items():
    print(f"  {coin:10s}: {metrics['tx_time']:>12s} | {metrics['fee']:>8s} | {metrics['tps']:>4d} TPS")

Litecoin

Litecoin is an improved version of Bitcoin, known as “digital silver”:

class LitecoinBlock:
    """Litecoin block"""

    def __init__(self, previous_hash: str, transactions: List[Dict]):
        self.previous_hash = previous_hash
        self.transactions = transactions
        self.timestamp = time.time()
        self.nonce = 0
        self.target_time = 150  # 2.5 minute target block time
        self.block_reward = 12.5  # Current block reward

    def mine_with_scrypt(self, difficulty: int) -> bool:
        """Mine with Scrypt algorithm (simulated)"""
        target = "0" * difficulty
        start_time = time.time()

        print(f"Starting Litecoin mining (Scrypt algorithm)...")

        for nonce in range(100000):  # Limit attempts
            # Simulate Scrypt hash calculation (actually more memory-intensive than SHA-256)
            candidate_data = f"{self.previous_hash}{self.timestamp}{nonce}"
            # In actual implementation, Scrypt algorithm would be used here
            hash_result = hashlib.sha256(candidate_data.encode()).hexdigest()

            if hash_result.startswith(target):
                end_time = time.time()
                print(f"Litecoin mining successful!")
                print(f"Nonce: {nonce}")
                print(f"Hash: {hash_result}")
                print(f"Time: {end_time - start_time:.2f}s")
                return True

        print("Litecoin mining demonstration ended")
        return False

# Litecoin feature comparison
print("\n=== Litecoin vs Bitcoin Comparison ===")

ltc_features = {
    "Bitcoin": {
        "Algorithm": "SHA-256",
        "Block time": "10 minutes",
        "Total supply": "21 million",
        "Current reward": "6.25 BTC",
        "Difficulty adjustment": "2016 blocks (~2 weeks)"
    },
    "Litecoin": {
        "Algorithm": "Scrypt",
        "Block time": "2.5 minutes",
        "Total supply": "84 million",
        "Current reward": "12.5 LTC",
        "Difficulty adjustment": "2016 blocks (~3.5 days)"
    }
}

for coin, features in ltc_features.items():
    print(f"\n{coin}:")
    for key, value in features.items():
        print(f"  {key}: {value}")

# Simulate Litecoin mining
ltc_block = LitecoinBlock("previous_hash_123", [{"tx": "sample"}])
ltc_block.mine_with_scrypt(difficulty=3)

Binance Coin (BNB)

Binance Coin is a platform token issued by Binance exchange:

class BNBToken:
    """Binance Coin smart contract (simplified version)"""

    def __init__(self):
        self.name = "Binance Coin"
        self.symbol = "BNB"
        self.decimals = 18
        self.total_supply = 200_000_000  # 200 million total supply
        self.balances = {}
        self.burn_events = []  # Burn records

    def transfer(self, from_addr: str, to_addr: str, amount: float) -> bool:
        """Token transfer"""
        if self.balances.get(from_addr, 0) < amount:
            return False

        self.balances[from_addr] = self.balances.get(from_addr, 0) - amount
        self.balances[to_addr] = self.balances.get(to_addr, 0) + amount
        return True

    def burn_tokens(self, amount: float) -> bool:
        """Burn tokens (Binance quarterly burn)"""
        if self.total_supply < amount:
            return False

        self.total_supply -= amount
        self.burn_events.append({
            "amount": amount,
            "timestamp": time.time(),
            "remaining_supply": self.total_supply
        })

        print(f"BNB burned: {amount:,.0f} BNB")
        print(f"Remaining supply: {self.total_supply:,.0f} BNB")
        return True

    def calculate_trading_discount(self, trading_fee: float, bnb_balance: float) -> float:
        """Calculate trading fee discount"""
        if bnb_balance >= 100:  # Simplified VIP level determination
            discount_rate = 0.25  # 25% discount
            return trading_fee * (1 - discount_rate)
        return trading_fee

# BNB function demonstration
print("\n=== Binance Coin Function Demonstration ===")

bnb = BNBToken()

# Simulate Binance quarterly burns
quarterly_burns = [2_123_456, 1_987_654, 2_456_789, 1_765_432]

print("Binance quarterly BNB burns:")
for i, burn_amount in enumerate(quarterly_burns, 1):
    bnb.burn_tokens(burn_amount)
    print(f"Quarter {i} burn completed\n")

# Trading fee discount demonstration
trading_fees = [100, 250, 500]  # USDT
bnb_holdings = [50, 150, 1000]  # BNB

print("BNB holding trading fee discount:")
for fee, holding in zip(trading_fees, bnb_holdings):
    discounted_fee = bnb.calculate_trading_discount(fee, holding)
    discount_pct = (fee - discounted_fee) / fee * 100
    print(f"Trading fee: ${fee} | BNB holding: {holding} | Discounted fee: ${discounted_fee:.2f} ({discount_pct:.0f}% discount)")

Token Standards and Classifications

ERC-20 Token Standard

from abc import ABC, abstractmethod

class IERC20(ABC):
    """ERC-20 token interface standard"""

    @abstractmethod
    def total_supply(self) -> int:
        """Return total token supply"""
        pass

    @abstractmethod
    def balance_of(self, account: str) -> int:
        """Return account balance"""
        pass

    @abstractmethod
    def transfer(self, to: str, amount: int) -> bool:
        """Transfer"""
        pass

    @abstractmethod
    def allowance(self, owner: str, spender: str) -> int:
        """Return allowance"""
        pass

    @abstractmethod
    def approve(self, spender: str, amount: int) -> bool:
        """Approve allowance"""
        pass

    @abstractmethod
    def transfer_from(self, from_addr: str, to: str, amount: int) -> bool:
        """Delegated transfer"""
        pass

class ERC20Token(IERC20):
    """ERC-20 token implementation"""

    def __init__(self, name: str, symbol: str, decimals: int = 18,
                 total_supply: int = 0):
        self.name = name
        self.symbol = symbol
        self.decimals = decimals
        self._total_supply = total_supply
        self._balances: Dict[str, int] = {}
        self._allowances: Dict[str, Dict[str, int]] = {}

        # Allocate entire supply to deployer
        if total_supply > 0:
            deployer = "0xDeployer"
            self._balances[deployer] = total_supply

    def total_supply(self) -> int:
        return self._total_supply

    def balance_of(self, account: str) -> int:
        return self._balances.get(account, 0)

    def transfer(self, to: str, amount: int) -> bool:
        return self._transfer("msg.sender", to, amount)

    def allowance(self, owner: str, spender: str) -> int:
        return self._allowances.get(owner, {}).get(spender, 0)

    def approve(self, spender: str, amount: int) -> bool:
        owner = "msg.sender"
        if owner not in self._allowances:
            self._allowances[owner] = {}
        self._allowances[owner][spender] = amount
        print(f"Approved: {owner} -> {spender}: {amount}")
        return True

    def transfer_from(self, from_addr: str, to: str, amount: int) -> bool:
        spender = "msg.sender"
        current_allowance = self.allowance(from_addr, spender)

        if current_allowance < amount:
            print("Insufficient allowance")
            return False

        # Decrease allowance
        self._allowances[from_addr][spender] = current_allowance - amount

        # Execute transfer
        return self._transfer(from_addr, to, amount)

    def _transfer(self, from_addr: str, to: str, amount: int) -> bool:
        if amount <= 0:
            return False

        from_balance = self.balance_of(from_addr)
        if from_balance < amount:
            print(f"Insufficient balance: {from_balance} < {amount}")
            return False

        # Execute transfer
        self._balances[from_addr] = from_balance - amount
        self._balances[to] = self.balance_of(to) + amount

        print(f"Transfer: {from_addr} -> {to}: {amount}")
        return True

# ERC-20 token demonstration
print("\n=== ERC-20 Token Demonstration ===")

# Create USDT token
usdt = ERC20Token(
    name="Tether USD",
    symbol="USDT",
    decimals=6,
    total_supply=50_000_000_000 * (10**6)  # 50 billion USDT
)

print(f"Token information:")
print(f"  Name: {usdt.name}")
print(f"  Symbol: {usdt.symbol}")
print(f"  Decimals: {usdt.decimals}")
print(f"  Total supply: {usdt.total_supply() / (10**usdt.decimals):,.0f} {usdt.symbol}")

# Simulate transfer operations
deployer = "0xDeployer"
alice = "0xAlice"
bob = "0xBob"

print(f"\nInitial balance:")
print(f"Deployer: {usdt.balance_of(deployer) / (10**usdt.decimals):,.0f} USDT")

# Deployer transfers to Alice
transfer_amount = 1000 * (10**usdt.decimals)  # 1000 USDT
usdt._balances["msg.sender"] = usdt._balances[deployer]  # Simulate msg.sender
success = usdt.transfer(alice, transfer_amount)

print(f"Transfer result: {success}")
print(f"Alice balance: {usdt.balance_of(alice) / (10**usdt.decimals):,.0f} USDT")

# Alice approves Bob for delegated transfer
approve_amount = 500 * (10**usdt.decimals)  # 500 USDT
usdt._allowances["msg.sender"] = usdt._allowances.get(alice, {})
usdt.approve(bob, approve_amount)

# Bob delegated transfer
transfer_amount_2 = 200 * (10**usdt.decimals)  # 200 USDT
charlie = "0xCharlie"
success = usdt.transfer_from(alice, charlie, transfer_amount_2)

print(f"Delegated transfer result: {success}")
print(f"Final balances:")
print(f"  Alice: {usdt.balance_of(alice) / (10**usdt.decimals):,.0f} USDT")
print(f"  Charlie: {usdt.balance_of(charlie) / (10**usdt.decimals):,.0f} USDT")
print(f"  Remaining allowance: {usdt.allowance(alice, bob) / (10**usdt.decimals):,.0f} USDT")

NFT Standard (ERC-721)

class ERC721Token:
    """ERC-721 NFT token"""

    def __init__(self, name: str, symbol: str):
        self.name = name
        self.symbol = symbol
        self._owners: Dict[int, str] = {}  # tokenId -> owner
        self._token_approvals: Dict[int, str] = {}  # tokenId -> approved
        self._operator_approvals: Dict[str, Dict[str, bool]] = {}  # owner -> operator -> approved
        self._token_uris: Dict[int, str] = {}  # tokenId -> tokenURI
        self._token_counter = 0

    def mint(self, to: str, token_uri: str) -> int:
        """Mint NFT"""
        token_id = self._token_counter
        self._owners[token_id] = to
        self._token_uris[token_id] = token_uri
        self._token_counter += 1

        print(f"NFT minted: Token #{token_id} -> {to}")
        print(f"Metadata URI: {token_uri}")
        return token_id

    def owner_of(self, token_id: int) -> str:
        """Get NFT owner"""
        return self._owners.get(token_id, "")

    def token_uri(self, token_id: int) -> str:
        """Get NFT metadata URI"""
        return self._token_uris.get(token_id, "")

    def transfer_from(self, from_addr: str, to: str, token_id: int) -> bool:
        """Transfer NFT"""
        if self._owners.get(token_id) != from_addr:
            print("Only owner can transfer NFT")
            return False

        self._owners[token_id] = to
        # Clear approval
        self._token_approvals.pop(token_id, None)

        print(f"NFT transferred: Token #{token_id} from {from_addr} to {to}")
        return True

    def approve(self, to: str, token_id: int):
        """Approve NFT"""
        owner = self._owners.get(token_id)
        if not owner:
            raise ValueError("Token does not exist")

        self._token_approvals[token_id] = to
        print(f"NFT approved: Token #{token_id} -> {to}")

    def get_collection_info(self) -> Dict:
        """Get collection information"""
        unique_owners = set(self._owners.values())
        return {
            "name": self.name,
            "symbol": self.symbol,
            "total_supply": len(self._owners),
            "unique_owners": len(unique_owners),
            "floor_price": "Determined by market"
        }

# NFT demonstration
print("\n=== NFT (ERC-721) Demonstration ===")

# Create CryptoPunks-style NFT collection
crypto_art = ERC721Token("Crypto Art Collection", "CAC")

# Mint NFTs
artists = ["0xArtist1", "0xArtist2", "0xCollector1"]
artworks = [
    "https://ipfs.io/ipfs/QmABC.../punk1.json",
    "https://ipfs.io/ipfs/QmDEF.../abstract2.json",
    "https://ipfs.io/ipfs/QmGHI.../portrait3.json"
]

token_ids = []
for artist, artwork_uri in zip(artists, artworks):
    token_id = crypto_art.mint(artist, artwork_uri)
    token_ids.append(token_id)

print(f"\nCollection information:")
collection_info = crypto_art.get_collection_info()
for key, value in collection_info.items():
    print(f"  {key}: {value}")

# NFT trading
print(f"\n=== NFT Trading ===")
buyer = "0xCollector2"
selling_token_id = token_ids[0]

print(f"Owner before trade: {crypto_art.owner_of(selling_token_id)}")

# Execute NFT transfer
success = crypto_art.transfer_from(
    crypto_art.owner_of(selling_token_id),
    buyer,
    selling_token_id
)

print(f"Owner after trade: {crypto_art.owner_of(selling_token_id)}")
print(f"NFT metadata: {crypto_art.token_uri(selling_token_id)}")

Chapter Summary

This chapter comprehensively introduced the characteristics and applications of mainstream virtual currencies:

  1. Ethereum Ecosystem:

    • Smart contracts and EVM
    • Gas mechanism and fee calculation
    • Rich DApp ecosystem
  2. Other Mainstream Coins:

    • Ripple: Fast cross-border payments, 3-5 second confirmation
    • Litecoin: Improved version of Bitcoin, 2.5-minute blocks
    • Binance Coin: Platform token, trading fee discounts
  3. Token Standards:

    • ERC-20: Fungible token standard
    • ERC-721: Non-fungible token (NFT) standard
    • Application scenarios for different standards
  4. Technical Comparison:

    • Performance metrics: TPS, confirmation time, fees
    • Consensus mechanisms: PoW, PoS, consortium chains
    • Application scenarios: payments, smart contracts, DeFi

Each virtual currency has its unique technical characteristics and application scenarios. Understanding these differences helps in selecting appropriate blockchain solutions. In the next chapter, we will learn about secure storage and wallet management of virtual currencies.