blockchain-expert

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Blockchain Expert

区块链专家

Expert guidance for blockchain development, smart contracts, Web3 applications, DeFi protocols, and cryptocurrency systems.
为区块链开发、智能合约、Web3应用、DeFi协议及加密货币系统提供专业指导。

Core Concepts

核心概念

Blockchain Fundamentals

区块链基础

  • Distributed ledger technology
  • Consensus mechanisms (PoW, PoS, PoA)
  • Cryptographic hashing
  • Public/private key cryptography
  • Transaction validation
  • Block structure and chain
  • 分布式账本技术
  • 共识机制(PoW、PoS、PoA)
  • 加密哈希
  • 公钥/私钥密码学
  • 交易验证
  • 区块结构与链

Smart Contracts

智能合约

  • Solidity programming
  • Gas optimization
  • Security patterns
  • Upgradeable contracts
  • Testing and auditing
  • Contract interactions
  • Solidity编程
  • Gas优化
  • 安全模式
  • 可升级合约
  • 测试与审计
  • 合约交互

Web3 & DeFi

Web3与DeFi

  • Decentralized applications (dApps)
  • DeFi protocols (AMM, lending, staking)
  • NFTs and token standards
  • Layer 2 solutions
  • Cross-chain bridges
  • Wallet integration
  • 去中心化应用(dApps)
  • DeFi协议(AMM、借贷、质押)
  • NFT与代币标准
  • Layer 2解决方案
  • 跨链桥
  • 钱包集成

Smart Contract Development

智能合约开发

solidity
// 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/ReentrancyGuard.sol";

contract SimpleToken is ERC20, Ownable, ReentrancyGuard {
    uint256 public constant MAX_SUPPLY = 1000000 * 10**18;

    mapping(address => bool) public minters;

    event MinterAdded(address indexed minter);
    event MinterRemoved(address indexed minter);

    modifier onlyMinter() {
        require(minters[msg.sender], "Not a minter");
        _;
    }

    constructor() ERC20("SimpleToken", "SMPL") {
        minters[msg.sender] = true;
    }

    function mint(address to, uint256 amount) external onlyMinter {
        require(totalSupply() + amount <= MAX_SUPPLY, "Max supply exceeded");
        _mint(to, amount);
    }

    function burn(uint256 amount) external {
        _burn(msg.sender, amount);
    }

    function addMinter(address minter) external onlyOwner {
        minters[minter] = true;
        emit MinterAdded(minter);
    }

    function removeMinter(address minter) external onlyOwner {
        minters[minter] = false;
        emit MinterRemoved(minter);
    }
}

// Staking Contract
contract StakingPool is ReentrancyGuard {
    IERC20 public stakingToken;
    IERC20 public rewardToken;

    uint256 public rewardRate = 100; // Reward tokens per second
    uint256 public lastUpdateTime;
    uint256 public rewardPerTokenStored;

    mapping(address => uint256) public userRewardPerTokenPaid;
    mapping(address => uint256) public rewards;
    mapping(address => uint256) public balances;

    uint256 private _totalSupply;

    constructor(address _stakingToken, address _rewardToken) {
        stakingToken = IERC20(_stakingToken);
        rewardToken = IERC20(_rewardToken);
    }

    function rewardPerToken() public view returns (uint256) {
        if (_totalSupply == 0) {
            return rewardPerTokenStored;
        }
        return rewardPerTokenStored +
               (((block.timestamp - lastUpdateTime) * rewardRate * 1e18) / _totalSupply);
    }

    function earned(address account) public view returns (uint256) {
        return ((balances[account] *
                (rewardPerToken() - userRewardPerTokenPaid[account])) / 1e18) +
               rewards[account];
    }

    modifier updateReward(address account) {
        rewardPerTokenStored = rewardPerToken();
        lastUpdateTime = block.timestamp;
        if (account != address(0)) {
            rewards[account] = earned(account);
            userRewardPerTokenPaid[account] = rewardPerTokenStored;
        }
        _;
    }

    function stake(uint256 amount) external nonReentrant updateReward(msg.sender) {
        require(amount > 0, "Cannot stake 0");
        _totalSupply += amount;
        balances[msg.sender] += amount;
        stakingToken.transferFrom(msg.sender, address(this), amount);
    }

    function withdraw(uint256 amount) external nonReentrant updateReward(msg.sender) {
        require(amount > 0, "Cannot withdraw 0");
        _totalSupply -= amount;
        balances[msg.sender] -= amount;
        stakingToken.transfer(msg.sender, amount);
    }

    function getReward() external nonReentrant updateReward(msg.sender) {
        uint256 reward = rewards[msg.sender];
        if (reward > 0) {
            rewards[msg.sender] = 0;
            rewardToken.transfer(msg.sender, reward);
        }
    }
}
solidity
// 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/ReentrancyGuard.sol";

contract SimpleToken is ERC20, Ownable, ReentrancyGuard {
    uint256 public constant MAX_SUPPLY = 1000000 * 10**18;

    mapping(address => bool) public minters;

    event MinterAdded(address indexed minter);
    event MinterRemoved(address indexed minter);

    modifier onlyMinter() {
        require(minters[msg.sender], "Not a minter");
        _;
    }

    constructor() ERC20("SimpleToken", "SMPL") {
        minters[msg.sender] = true;
    }

    function mint(address to, uint256 amount) external onlyMinter {
        require(totalSupply() + amount <= MAX_SUPPLY, "Max supply exceeded");
        _mint(to, amount);
    }

    function burn(uint256 amount) external {
        _burn(msg.sender, amount);
    }

    function addMinter(address minter) external onlyOwner {
        minters[minter] = true;
        emit MinterAdded(minter);
    }

    function removeMinter(address minter) external onlyOwner {
        minters[minter] = false;
        emit MinterRemoved(minter);
    }
}

// Staking Contract
contract StakingPool is ReentrancyGuard {
    IERC20 public stakingToken;
    IERC20 public rewardToken;

    uint256 public rewardRate = 100; // Reward tokens per second
    uint256 public lastUpdateTime;
    uint256 public rewardPerTokenStored;

    mapping(address => uint256) public userRewardPerTokenPaid;
    mapping(address => uint256) public rewards;
    mapping(address => uint256) public balances;

    uint256 private _totalSupply;

    constructor(address _stakingToken, address _rewardToken) {
        stakingToken = IERC20(_stakingToken);
        rewardToken = IERC20(_rewardToken);
    }

    function rewardPerToken() public view returns (uint256) {
        if (_totalSupply == 0) {
            return rewardPerTokenStored;
        }
        return rewardPerTokenStored +
               (((block.timestamp - lastUpdateTime) * rewardRate * 1e18) / _totalSupply);
    }

    function earned(address account) public view returns (uint256) {
        return ((balances[account] *
                (rewardPerToken() - userRewardPerTokenPaid[account])) / 1e18) +
               rewards[account];
    }

    modifier updateReward(address account) {
        rewardPerTokenStored = rewardPerToken();
        lastUpdateTime = block.timestamp;
        if (account != address(0)) {
            rewards[account] = earned(account);
            userRewardPerTokenPaid[account] = rewardPerTokenStored;
        }
        _;
    }

    function stake(uint256 amount) external nonReentrant updateReward(msg.sender) {
        require(amount > 0, "Cannot stake 0");
        _totalSupply += amount;
        balances[msg.sender] += amount;
        stakingToken.transferFrom(msg.sender, address(this), amount);
    }

    function withdraw(uint256 amount) external nonReentrant updateReward(msg.sender) {
        require(amount > 0, "Cannot withdraw 0");
        _totalSupply -= amount;
        balances[msg.sender] -= amount;
        stakingToken.transfer(msg.sender, amount);
    }

    function getReward() external nonReentrant updateReward(msg.sender) {
        uint256 reward = rewards[msg.sender];
        if (reward > 0) {
            rewards[msg.sender] = 0;
            rewardToken.transfer(msg.sender, reward);
        }
    }
}

DeFi: AMM Implementation

DeFi:AMM实现

solidity
// Simple Automated Market Maker (like Uniswap)
contract SimpleAMM is ReentrancyGuard {
    IERC20 public token0;
    IERC20 public token1;

    uint256 public reserve0;
    uint256 public reserve1;

    uint256 public totalSupply;
    mapping(address => uint256) public balanceOf;

    event Swap(address indexed user, address tokenIn, uint256 amountIn, uint256 amountOut);
    event AddLiquidity(address indexed user, uint256 amount0, uint256 amount1);
    event RemoveLiquidity(address indexed user, uint256 amount0, uint256 amount1);

    constructor(address _token0, address _token1) {
        token0 = IERC20(_token0);
        token1 = IERC20(_token1);
    }

    function addLiquidity(uint256 amount0, uint256 amount1)
        external
        nonReentrant
        returns (uint256 shares)
    {
        token0.transferFrom(msg.sender, address(this), amount0);
        token1.transferFrom(msg.sender, address(this), amount1);

        if (totalSupply == 0) {
            shares = sqrt(amount0 * amount1);
        } else {
            shares = min(
                (amount0 * totalSupply) / reserve0,
                (amount1 * totalSupply) / reserve1
            );
        }

        require(shares > 0, "Shares = 0");

        _mint(msg.sender, shares);
        _update(
            token0.balanceOf(address(this)),
            token1.balanceOf(address(this))
        );

        emit AddLiquidity(msg.sender, amount0, amount1);
    }

    function removeLiquidity(uint256 shares)
        external
        nonReentrant
        returns (uint256 amount0, uint256 amount1)
    {
        uint256 balance0 = token0.balanceOf(address(this));
        uint256 balance1 = token1.balanceOf(address(this));

        amount0 = (shares * balance0) / totalSupply;
        amount1 = (shares * balance1) / totalSupply;

        require(amount0 > 0 && amount1 > 0, "Amount = 0");

        _burn(msg.sender, shares);
        _update(balance0 - amount0, balance1 - amount1);

        token0.transfer(msg.sender, amount0);
        token1.transfer(msg.sender, amount1);

        emit RemoveLiquidity(msg.sender, amount0, amount1);
    }

    function swap(address tokenIn, uint256 amountIn)
        external
        nonReentrant
        returns (uint256 amountOut)
    {
        require(tokenIn == address(token0) || tokenIn == address(token1), "Invalid token");

        bool isToken0 = tokenIn == address(token0);

        (IERC20 tokenIn_, IERC20 tokenOut, uint256 reserveIn, uint256 reserveOut) =
            isToken0
                ? (token0, token1, reserve0, reserve1)
                : (token1, token0, reserve1, reserve0);

        tokenIn_.transferFrom(msg.sender, address(this), amountIn);

        // 0.3% fee
        uint256 amountInWithFee = (amountIn * 997) / 1000;

        // x * y = k formula
        amountOut = (reserveOut * amountInWithFee) / (reserveIn + amountInWithFee);

        tokenOut.transfer(msg.sender, amountOut);

        _update(
            token0.balanceOf(address(this)),
            token1.balanceOf(address(this))
        );

        emit Swap(msg.sender, tokenIn, amountIn, amountOut);
    }

    function _mint(address to, uint256 amount) private {
        balanceOf[to] += amount;
        totalSupply += amount;
    }

    function _burn(address from, uint256 amount) private {
        balanceOf[from] -= amount;
        totalSupply -= amount;
    }

    function _update(uint256 _reserve0, uint256 _reserve1) private {
        reserve0 = _reserve0;
        reserve1 = _reserve1;
    }

    function sqrt(uint256 y) private pure returns (uint256 z) {
        if (y > 3) {
            z = y;
            uint256 x = y / 2 + 1;
            while (x < z) {
                z = x;
                x = (y / x + x) / 2;
            }
        } else if (y != 0) {
            z = 1;
        }
    }

    function min(uint256 x, uint256 y) private pure returns (uint256) {
        return x <= y ? x : y;
    }
}
solidity
// Simple Automated Market Maker (like Uniswap)
contract SimpleAMM is ReentrancyGuard {
    IERC20 public token0;
    IERC20 public token1;

    uint256 public reserve0;
    uint256 public reserve1;

    uint256 public totalSupply;
    mapping(address => uint256) public balanceOf;

    event Swap(address indexed user, address tokenIn, uint256 amountIn, uint256 amountOut);
    event AddLiquidity(address indexed user, uint256 amount0, uint256 amount1);
    event RemoveLiquidity(address indexed user, uint256 amount0, uint256 amount1);

    constructor(address _token0, address _token1) {
        token0 = IERC20(_token0);
        token1 = IERC20(_token1);
    }

    function addLiquidity(uint256 amount0, uint256 amount1)
        external
        nonReentrant
        returns (uint256 shares)
    {
        token0.transferFrom(msg.sender, address(this), amount0);
        token1.transferFrom(msg.sender, address(this), amount1);

        if (totalSupply == 0) {
            shares = sqrt(amount0 * amount1);
        } else {
            shares = min(
                (amount0 * totalSupply) / reserve0,
                (amount1 * totalSupply) / reserve1
            );
        }

        require(shares > 0, "Shares = 0");

        _mint(msg.sender, shares);
        _update(
            token0.balanceOf(address(this)),
            token1.balanceOf(address(this))
        );

        emit AddLiquidity(msg.sender, amount0, amount1);
    }

    function removeLiquidity(uint256 shares)
        external
        nonReentrant
        returns (uint256 amount0, uint256 amount1)
    {
        uint256 balance0 = token0.balanceOf(address(this));
        uint256 balance1 = token1.balanceOf(address(this));

        amount0 = (shares * balance0) / totalSupply;
        amount1 = (shares * balance1) / totalSupply;

        require(amount0 > 0 && amount1 > 0, "Amount = 0");

        _burn(msg.sender, shares);
        _update(balance0 - amount0, balance1 - amount1);

        token0.transfer(msg.sender, amount0);
        token1.transfer(msg.sender, amount1);

        emit RemoveLiquidity(msg.sender, amount0, amount1);
    }

    function swap(address tokenIn, uint256 amountIn)
        external
        nonReentrant
        returns (uint256 amountOut)
    {
        require(tokenIn == address(token0) || tokenIn == address(token1), "Invalid token");

        bool isToken0 = tokenIn == address(token0);

        (IERC20 tokenIn_, IERC20 tokenOut, uint256 reserveIn, uint256 reserveOut) =
            isToken0
                ? (token0, token1, reserve0, reserve1)
                : (token1, token0, reserve1, reserve0);

        tokenIn_.transferFrom(msg.sender, address(this), amountIn);

        // 0.3% fee
        uint256 amountInWithFee = (amountIn * 997) / 1000;

        // x * y = k formula
        amountOut = (reserveOut * amountInWithFee) / (reserveIn + amountInWithFee);

        tokenOut.transfer(msg.sender, amountOut);

        _update(
            token0.balanceOf(address(this)),
            token1.balanceOf(address(this))
        );

        emit Swap(msg.sender, tokenIn, amountIn, amountOut);
    }

    function _mint(address to, uint256 amount) private {
        balanceOf[to] += amount;
        totalSupply += amount;
    }

    function _burn(address from, uint256 amount) private {
        balanceOf[from] -= amount;
        totalSupply -= amount;
    }

    function _update(uint256 _reserve0, uint256 _reserve1) private {
        reserve0 = _reserve0;
        reserve1 = _reserve1;
    }

    function sqrt(uint256 y) private pure returns (uint256 z) {
        if (y > 3) {
            z = y;
            uint256 x = y / 2 + 1;
            while (x < z) {
                z = x;
                x = (y / x + x) / 2;
            }
        } else if (y != 0) {
            z = 1;
        }
    }

    function min(uint256 x, uint256 y) private pure returns (uint256) {
        return x <= y ? x : y;
    }
}

Web3 Integration

Web3集成

typescript
import { ethers } from 'ethers';
import { Contract, Provider, Signer } from 'ethers';

class Web3Client {
    private provider: Provider;
    private signer?: Signer;

    constructor(rpcUrl: string) {
        this.provider = new ethers.JsonRpcProvider(rpcUrl);
    }

    async connectWallet(): Promise<string> {
        // Connect to MetaMask
        if (typeof window.ethereum !== 'undefined') {
            const provider = new ethers.BrowserProvider(window.ethereum);
            await provider.send("eth_requestAccounts", []);
            this.signer = await provider.getSigner();
            return await this.signer.getAddress();
        }
        throw new Error('No wallet found');
    }

    async getBalance(address: string): Promise<string> {
        const balance = await this.provider.getBalance(address);
        return ethers.formatEther(balance);
    }

    async sendTransaction(to: string, amount: string): Promise<string> {
        if (!this.signer) throw new Error('Wallet not connected');

        const tx = await this.signer.sendTransaction({
            to,
            value: ethers.parseEther(amount)
        });

        const receipt = await tx.wait();
        return receipt?.hash || '';
    }

    getContract(address: string, abi: any[]): Contract {
        return new ethers.Contract(
            address,
            abi,
            this.signer || this.provider
        );
    }

    async callContract(
        contractAddress: string,
        abi: any[],
        method: string,
        args: any[]
    ): Promise<any> {
        const contract = this.getContract(contractAddress, abi);
        return await contract[method](...args);
    }

    async estimateGas(
        contractAddress: string,
        abi: any[],
        method: string,
        args: any[]
    ): Promise<bigint> {
        const contract = this.getContract(contractAddress, abi);
        return await contract[method].estimateGas(...args);
    }
}
typescript
import { ethers } from 'ethers';
import { Contract, Provider, Signer } from 'ethers';

class Web3Client {
    private provider: Provider;
    private signer?: Signer;

    constructor(rpcUrl: string) {
        this.provider = new ethers.JsonRpcProvider(rpcUrl);
    }

    async connectWallet(): Promise<string> {
        // Connect to MetaMask
        if (typeof window.ethereum !== 'undefined') {
            const provider = new ethers.BrowserProvider(window.ethereum);
            await provider.send("eth_requestAccounts", []);
            this.signer = await provider.getSigner();
            return await this.signer.getAddress();
        }
        throw new Error('No wallet found');
    }

    async getBalance(address: string): Promise<string> {
        const balance = await this.provider.getBalance(address);
        return ethers.formatEther(balance);
    }

    async sendTransaction(to: string, amount: string): Promise<string> {
        if (!this.signer) throw new Error('Wallet not connected');

        const tx = await this.signer.sendTransaction({
            to,
            value: ethers.parseEther(amount)
        });

        const receipt = await tx.wait();
        return receipt?.hash || '';
    }

    getContract(address: string, abi: any[]): Contract {
        return new ethers.Contract(
            address,
            abi,
            this.signer || this.provider
        );
    }

    async callContract(
        contractAddress: string,
        abi: any[],
        method: string,
        args: any[]
    ): Promise<any> {
        const contract = this.getContract(contractAddress, abi);
        return await contract[method](...args);
    }

    async estimateGas(
        contractAddress: string,
        abi: any[],
        method: string,
        args: any[]
    ): Promise<bigint> {
        const contract = this.getContract(contractAddress, abi);
        return await contract[method].estimateGas(...args);
    }
}

Best Practices

最佳实践

Smart Contract Security

智能合约安全

  • Use OpenZeppelin contracts for standards
  • Implement reentrancy guards
  • Check for integer overflow/underflow (use Solidity 0.8+)
  • Validate all inputs
  • Use pull over push for payments
  • Implement circuit breakers for emergencies
  • Comprehensive testing and auditing
  • 使用OpenZeppelin合约实现标准功能
  • 实现重入保护
  • 检查整数溢出/下溢(使用Solidity 0.8+版本)
  • 验证所有输入
  • 采用“拉取”而非“推送”的支付方式
  • 为紧急情况实现断路器机制
  • 全面的测试与审计

Gas Optimization

Gas优化

  • Use
    uint256
    over smaller types
  • Pack storage variables
  • Use
    calldata
    for function parameters
  • Minimize storage operations
  • Use events for data that doesn't need on-chain storage
  • Batch operations when possible
  • 优先使用
    uint256
    而非更小的类型
  • 打包存储变量
  • 对函数参数使用
    calldata
  • 尽量减少存储操作
  • 使用事件存储无需上链的数据
  • 尽可能批量操作

Development

开发流程

  • Use Hardhat/Foundry for development
  • Write comprehensive tests
  • Use test networks before mainnet
  • Implement upgrade patterns carefully
  • Monitor contract events
  • Document all functions
  • 使用Hardhat/Foundry进行开发
  • 编写全面的测试用例
  • 主网部署前先在测试网验证
  • 谨慎实现升级模式
  • 监控合约事件
  • 为所有函数编写文档

Anti-Patterns

反模式

❌ No reentrancy protection ❌ Unchecked external calls ❌ Using
tx.origin
for authorization ❌ Floating pragma versions ❌ No access control ❌ Storing sensitive data on-chain ❌ No gas limit considerations
❌ 未实现重入保护 ❌ 未检查外部调用 ❌ 使用
tx.origin
进行授权 ❌ 浮动pragma版本 ❌ 无访问控制 ❌ 在链上存储敏感数据 ❌ 未考虑Gas限制

Resources

资源