HiHuo
首页
博客
手册
工具
关于
首页
博客
手册
工具
关于
  • Web3 完整技术体系

    • Web3 完整技术体系
    • 区块链基础与密码学
    • 第一章:比特币原理与实现
    • 第二章:以太坊架构与核心概念
    • Solidity智能合约开发基础
    • 04-Solidity进阶与安全
    • 05-ERC标准详解
    • 06-DeFi核心协议-去中心化交易所
    • 07-DeFi核心协议-借贷协议
    • 08-DeFi核心协议-稳定币
    • NFT与元宇宙
    • Layer2扩容方案
    • 跨链技术
    • Web3前端开发
    • 链下数据与预言机
    • 智能合约测试与部署
    • MEV与交易优化
    • DAO治理
    • 项目实战:完整DeFi借贷协议

08-DeFi核心协议-稳定币

第一部分:稳定币基础

1.1 稳定币概述

稳定币是价格与法币(通常是美元)挂钩的加密货币,旨在减少价格波动。

1.1.1 稳定币的重要性

  1. 价值存储:在加密市场提供稳定的价值载体
  2. 交易媒介:DeFi中的主要交易对
  3. 记账单位:衡量其他资产价值的基准
  4. 桥梁作用:连接传统金融和加密世界

1.2 稳定币分类

稳定币类型
├── 法币抵押型
│   ├── USDT (Tether)
│   ├── USDC (Circle)
│   └── BUSD (Binance)
│
├── 加密资产抵押型
│   ├── DAI (MakerDAO)
│   ├── sUSD (Synthetix)
│   └── LUSD (Liquity)
│
└── 算法稳定币
    ├── UST (已崩盘)
    ├── FRAX (部分抵押)
    └── AMPL (Rebase机制)

1.3 稳定机制对比

类型抵押品去中心化程度资本效率风险
法币抵押法币低高(1:1)中心化风险、监管风险
加密抵押加密资产高低(超额抵押)价格波动风险
算法稳定算法高高死亡螺旋风险

第二部分:法币抵押型稳定币(USDC)

2.1 USDC原理

USDC由Circle发行,每个USDC由1美元储备金支持,储备金由受监管的金融机构托管。

2.2 USDC合约实现

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

/**
 * @title USDC
 * @dev 法币抵押型稳定币实现(类似USDC)
 */
contract USDC {
    string public constant name = "USD Coin";
    string public constant symbol = "USDC";
    uint8 public constant decimals = 6;

    uint256 private _totalSupply;
    mapping(address => uint256) private _balances;
    mapping(address => mapping(address => uint256)) private _allowances;

    // 角色管理
    address public owner;
    mapping(address => bool) public minters;
    mapping(address => bool) public blacklisted;

    // 铸造限额
    mapping(address => uint256) public minterAllowance;

    // 暂停功能
    bool public paused;

    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(address indexed owner, address indexed spender, uint256 value);
    event Mint(address indexed minter, address indexed to, uint256 amount);
    event Burn(address indexed burner, uint256 amount);
    event MinterConfigured(address indexed minter, uint256 allowance);
    event MinterRemoved(address indexed minter);
    event Blacklisted(address indexed account);
    event UnBlacklisted(address indexed account);
    event Paused();
    event Unpaused();

    modifier onlyOwner() {
        require(msg.sender == owner, "Not owner");
        _;
    }

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

    modifier notBlacklisted(address account) {
        require(!blacklisted[account], "Account blacklisted");
        _;
    }

    modifier whenNotPaused() {
        require(!paused, "Paused");
        _;
    }

    constructor() {
        owner = msg.sender;
    }

    /**
     * @dev 配置铸造者
     */
    function configureMinter(address minter, uint256 allowance) external onlyOwner {
        minters[minter] = true;
        minterAllowance[minter] = allowance;
        emit MinterConfigured(minter, allowance);
    }

    /**
     * @dev 移除铸造者
     */
    function removeMinter(address minter) external onlyOwner {
        minters[minter] = false;
        minterAllowance[minter] = 0;
        emit MinterRemoved(minter);
    }

    /**
     * @dev 铸造代币
     */
    function mint(address to, uint256 amount)
        external
        onlyMinters
        whenNotPaused
        notBlacklisted(to)
        returns (bool)
    {
        require(to != address(0), "Mint to zero address");
        require(amount > 0, "Mint amount must be positive");
        require(amount <= minterAllowance[msg.sender], "Exceeds minter allowance");

        minterAllowance[msg.sender] -= amount;
        _totalSupply += amount;
        _balances[to] += amount;

        emit Mint(msg.sender, to, amount);
        emit Transfer(address(0), to, amount);

        return true;
    }

    /**
     * @dev 销毁代币
     */
    function burn(uint256 amount) external onlyMinters whenNotPaused {
        require(amount > 0, "Burn amount must be positive");
        require(_balances[msg.sender] >= amount, "Insufficient balance");

        _balances[msg.sender] -= amount;
        _totalSupply -= amount;

        emit Burn(msg.sender, amount);
        emit Transfer(msg.sender, address(0), amount);
    }

    /**
     * @dev 加入黑名单
     */
    function blacklist(address account) external onlyOwner {
        blacklisted[account] = true;
        emit Blacklisted(account);
    }

    /**
     * @dev 移出黑名单
     */
    function unBlacklist(address account) external onlyOwner {
        blacklisted[account] = false;
        emit UnBlacklisted(account);
    }

    /**
     * @dev 暂停
     */
    function pause() external onlyOwner {
        paused = true;
        emit Paused();
    }

    /**
     * @dev 恢复
     */
    function unpause() external onlyOwner {
        paused = false;
        emit Unpaused();
    }

    /**
     * @dev 转账
     */
    function transfer(address recipient, uint256 amount)
        external
        whenNotPaused
        notBlacklisted(msg.sender)
        notBlacklisted(recipient)
        returns (bool)
    {
        _transfer(msg.sender, recipient, amount);
        return true;
    }

    /**
     * @dev 授权
     */
    function approve(address spender, uint256 amount)
        external
        whenNotPaused
        notBlacklisted(msg.sender)
        notBlacklisted(spender)
        returns (bool)
    {
        _approve(msg.sender, spender, amount);
        return true;
    }

    /**
     * @dev 授权转账
     */
    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    )
        external
        whenNotPaused
        notBlacklisted(sender)
        notBlacklisted(msg.sender)
        notBlacklisted(recipient)
        returns (bool)
    {
        _transfer(sender, recipient, amount);

        uint256 currentAllowance = _allowances[sender][msg.sender];
        require(currentAllowance >= amount, "Transfer amount exceeds allowance");
        unchecked {
            _approve(sender, msg.sender, currentAllowance - amount);
        }

        return true;
    }

    // 查询函数
    function totalSupply() external view returns (uint256) {
        return _totalSupply;
    }

    function balanceOf(address account) external view returns (uint256) {
        return _balances[account];
    }

    function allowance(address owner_, address spender) external view returns (uint256) {
        return _allowances[owner_][spender];
    }

    // 内部函数
    function _transfer(
        address sender,
        address recipient,
        uint256 amount
    ) internal {
        require(sender != address(0), "Transfer from zero address");
        require(recipient != address(0), "Transfer to zero address");

        uint256 senderBalance = _balances[sender];
        require(senderBalance >= amount, "Transfer amount exceeds balance");

        unchecked {
            _balances[sender] = senderBalance - amount;
        }
        _balances[recipient] += amount;

        emit Transfer(sender, recipient, amount);
    }

    function _approve(
        address owner_,
        address spender,
        uint256 amount
    ) internal {
        require(owner_ != address(0), "Approve from zero address");
        require(spender != address(0), "Approve to zero address");

        _allowances[owner_][spender] = amount;
        emit Approval(owner_, spender, amount);
    }
}

第三部分:加密资产抵押型稳定币(DAI)

3.1 MakerDAO和DAI原理

DAI是由MakerDAO发行的去中心化稳定币,通过超额抵押加密资产(如ETH)生成。

3.1.1 核心概念

CDP/Vault(金库):

  • 用户存入ETH等抵押品
  • 生成DAI
  • 抵押率通常为150%以上

稳定费(Stability Fee):

  • 借DAI的利息
  • 用于维持系统稳定

清算:

  • 当抵押率低于清算线(如150%)
  • 清算人可拍卖抵押品
  • 偿还债务并获得折扣

DAI储蓄率(DSR):

  • 持有DAI可获得利息
  • 吸引用户持有DAI

3.2 MakerDAO核心合约

3.2.1 Vat(核心账本)

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

/**
 * @title Vat
 * @dev MakerDAO的核心账本合约(简化版)
 */
contract Vat {
    // 抵押品类型
    struct Ilk {
        uint256 Art; // 总债务(标准化)
        uint256 rate; // 累计利率
        uint256 spot; // 清算价格(含安全边际)
        uint256 line; // 债务上限
        uint256 dust; // 最小债务
    }

    // 金库(CDP)
    struct Urn {
        uint256 ink; // 抵押品数量
        uint256 art; // 债务(标准化)
    }

    // 抵押品类型映射
    mapping(bytes32 => Ilk) public ilks;

    // 金库映射: ilk => user => Urn
    mapping(bytes32 => mapping(address => Urn)) public urns;

    // 抵押品余额: ilk => user => amount
    mapping(bytes32 => mapping(address => uint256)) public gem;

    // DAI余额
    mapping(address => uint256) public dai;

    // 系统债务
    uint256 public debt;

    // 全局债务上限
    uint256 public Line;

    // 授权地址
    mapping(address => uint256) public wards;

    event LogNote(bytes4 indexed sig, bytes32 indexed arg1, bytes32 indexed arg2, bytes data);

    modifier auth() {
        require(wards[msg.sender] == 1, "Vat/not-authorized");
        _;
    }

    constructor() {
        wards[msg.sender] = 1;
    }

    /**
     * @dev 授权地址
     */
    function rely(address usr) external auth {
        wards[usr] = 1;
    }

    /**
     * @dev 取消授权
     */
    function deny(address usr) external auth {
        wards[usr] = 0;
    }

    /**
     * @dev 初始化抵押品类型
     */
    function init(bytes32 ilk) external auth {
        require(ilks[ilk].rate == 0, "Vat/ilk-already-init");
        ilks[ilk].rate = 10**27; // 初始利率为1
    }

    /**
     * @dev 存入抵押品
     */
    function slip(
        bytes32 ilk,
        address usr,
        int256 wad
    ) external auth {
        gem[ilk][usr] = _add(gem[ilk][usr], wad);
    }

    /**
     * @dev 调整CDP(核心函数)
     * @param ilk 抵押品类型
     * @param u 金库所有者
     * @param v 抵押品接收者
     * @param w DAI接收者
     * @param dink 抵押品变化量
     * @param dart 债务变化量
     */
    function frob(
        bytes32 ilk,
        address u,
        address v,
        address w,
        int256 dink,
        int256 dart
    ) external {
        Urn storage urn = urns[ilk][u];
        Ilk storage ilkData = ilks[ilk];

        // 更新金库
        urn.ink = _add(urn.ink, dink);
        urn.art = _add(urn.art, dart);

        // 更新抵押品类型的总债务
        ilkData.Art = _add(ilkData.Art, dart);

        // 计算实际债务(debt = art * rate)
        int256 dtab = _mul(ilkData.rate, dart);

        // 更新总债务
        debt = _add(debt, dtab);

        // 检查
        require(dart <= 0 || (ilkData.Art * ilkData.rate <= ilkData.line && debt <= Line), "Vat/ceiling-exceeded");

        require(dart <= 0 || _mul(urn.art, ilkData.rate) >= ilkData.dust, "Vat/dust");

        require(
            dart >= 0 || _mul(urn.art, ilkData.rate) >= ilkData.dust || (_mul(urn.art, ilkData.rate) == 0),
            "Vat/dust"
        );

        require(
            dink >= 0 || urn.ink >= 0,
            "Vat/not-safe"
        );

        require(
            dart <= 0 || (_mul(urn.ink, ilkData.spot) >= _mul(urn.art, ilkData.rate)),
            "Vat/not-safe"
        );

        // 转移抵押品
        gem[ilk][v] = _sub(gem[ilk][v], dink);

        // 转移DAI
        dai[w] = _add(dai[w], dtab);
    }

    /**
     * @dev 清算金库
     */
    function grab(
        bytes32 ilk,
        address u,
        address v,
        address w,
        int256 dink,
        int256 dart
    ) external auth {
        Urn storage urn = urns[ilk][u];
        Ilk storage ilkData = ilks[ilk];

        urn.ink = _add(urn.ink, dink);
        urn.art = _add(urn.art, dart);
        ilkData.Art = _add(ilkData.Art, dart);

        int256 dtab = _mul(ilkData.rate, dart);

        gem[ilk][v] = _sub(gem[ilk][v], dink);
        dai[w] = _sub(dai[w], dtab);
    }

    /**
     * @dev 更新利率
     */
    function fold(
        bytes32 ilk,
        address u,
        int256 rate_
    ) external auth {
        Ilk storage ilkData = ilks[ilk];
        ilkData.rate = _add(ilkData.rate, rate_);
        int256 rad = _mul(ilkData.Art, rate_);
        dai[u] = _add(dai[u], rad);
        debt = _add(debt, rad);
    }

    // 数学辅助函数
    function _add(uint256 x, int256 y) internal pure returns (uint256 z) {
        z = x + uint256(y);
        require(y >= 0 || z <= x, "Vat/add-overflow");
        require(y <= 0 || z >= x, "Vat/add-underflow");
    }

    function _sub(uint256 x, int256 y) internal pure returns (uint256 z) {
        z = x - uint256(y);
        require(y <= 0 || z <= x, "Vat/sub-overflow");
        require(y >= 0 || z >= x, "Vat/sub-underflow");
    }

    function _mul(uint256 x, int256 y) internal pure returns (int256 z) {
        z = int256(x) * y;
        require(int256(x) >= 0, "Vat/mul-uint-int-overflow");
        require(y == 0 || z / y == int256(x), "Vat/mul-overflow");
    }
}

3.2.2 简化的DAI合约

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

/**
 * @title DAI
 * @dev DAI稳定币合约(简化版)
 */
contract DAI {
    string public constant name = "Dai Stablecoin";
    string public constant symbol = "DAI";
    uint8 public constant decimals = 18;
    string public constant version = "1";

    uint256 private _totalSupply;
    mapping(address => uint256) private _balances;
    mapping(address => mapping(address => uint256)) private _allowances;

    // 授权地址
    mapping(address => uint256) public wards;

    // EIP-2612 Permit
    mapping(address => uint256) public nonces;
    bytes32 public DOMAIN_SEPARATOR;
    bytes32 public constant PERMIT_TYPEHASH =
        keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");

    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(address indexed owner, address indexed spender, uint256 value);

    modifier auth() {
        require(wards[msg.sender] == 1, "DAI/not-authorized");
        _;
    }

    constructor(uint256 chainId) {
        wards[msg.sender] = 1;

        DOMAIN_SEPARATOR = keccak256(
            abi.encode(
                keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
                keccak256(bytes(name)),
                keccak256(bytes(version)),
                chainId,
                address(this)
            )
        );
    }

    /**
     * @dev 授权
     */
    function rely(address usr) external auth {
        wards[usr] = 1;
    }

    /**
     * @dev 取消授权
     */
    function deny(address usr) external auth {
        wards[usr] = 0;
    }

    /**
     * @dev 铸造DAI
     */
    function mint(address usr, uint256 wad) external auth {
        _balances[usr] += wad;
        _totalSupply += wad;
        emit Transfer(address(0), usr, wad);
    }

    /**
     * @dev 销毁DAI
     */
    function burn(address usr, uint256 wad) external auth {
        require(_balances[usr] >= wad, "DAI/insufficient-balance");
        _balances[usr] -= wad;
        _totalSupply -= wad;
        emit Transfer(usr, address(0), wad);
    }

    /**
     * @dev Permit授权
     */
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external {
        require(block.timestamp <= deadline, "DAI/permit-expired");

        bytes32 digest = keccak256(
            abi.encodePacked(
                "\x19\x01",
                DOMAIN_SEPARATOR,
                keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, nonces[owner]++, deadline))
            )
        );

        address recoveredAddress = ecrecover(digest, v, r, s);
        require(recoveredAddress != address(0) && recoveredAddress == owner, "DAI/invalid-permit");

        _allowances[owner][spender] = value;
        emit Approval(owner, spender, value);
    }

    // ERC20标准函数
    function totalSupply() external view returns (uint256) {
        return _totalSupply;
    }

    function balanceOf(address account) external view returns (uint256) {
        return _balances[account];
    }

    function allowance(address owner, address spender) external view returns (uint256) {
        return _allowances[owner][spender];
    }

    function transfer(address recipient, uint256 amount) external returns (bool) {
        _transfer(msg.sender, recipient, amount);
        return true;
    }

    function approve(address spender, uint256 amount) external returns (bool) {
        _allowances[msg.sender][spender] = amount;
        emit Approval(msg.sender, spender, amount);
        return true;
    }

    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) external returns (bool) {
        require(_allowances[sender][msg.sender] >= amount, "DAI/insufficient-allowance");
        _allowances[sender][msg.sender] -= amount;
        _transfer(sender, recipient, amount);
        return true;
    }

    function _transfer(
        address sender,
        address recipient,
        uint256 amount
    ) internal {
        require(_balances[sender] >= amount, "DAI/insufficient-balance");
        _balances[sender] -= amount;
        _balances[recipient] += amount;
        emit Transfer(sender, recipient, amount);
    }
}

3.2.3 简化的MakerDAO系统

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

/**
 * @title SimpleMaker
 * @dev 简化的MakerDAO系统,便于理解核心机制
 */
contract SimpleMaker {
    // DAI代币
    DAI public dai;

    // 抵押品信息
    struct Collateral {
        uint256 totalDeposited; // 总抵押量
        uint256 totalDebt; // 总债务
        uint256 liquidationRatio; // 清算比率(150% = 150)
        uint256 stabilityFee; // 稳定费率(年化,2% = 2)
        uint256 debtCeiling; // 债务上限
        uint256 price; // 当前价格
        bool isActive; // 是否激活
    }

    // 金库信息
    struct Vault {
        uint256 collateral; // 抵押品数量
        uint256 debt; // 债务数量
        uint256 lastUpdate; // 上次更新时间
        uint256 accumulatedFee; // 累计费用
    }

    // 抵押品类型映射
    mapping(address => Collateral) public collaterals;

    // 用户金库: user => collateralType => Vault
    mapping(address => mapping(address => Vault)) public vaults;

    // 清算惩罚(13% = 113)
    uint256 public constant LIQUIDATION_PENALTY = 113;

    // DSR(DAI储蓄率)
    uint256 public dsr = 0; // 0%

    // DSR余额
    mapping(address => uint256) public dsrBalance;
    mapping(address => uint256) public dsrTimestamp;

    address public owner;

    event VaultOpened(address indexed user, address indexed collateralType);
    event CollateralDeposited(address indexed user, address indexed collateralType, uint256 amount);
    event CollateralWithdrawn(address indexed user, address indexed collateralType, uint256 amount);
    event DAIMinted(address indexed user, address indexed collateralType, uint256 amount);
    event DAIRepaid(address indexed user, address indexed collateralType, uint256 amount);
    event VaultLiquidated(
        address indexed user,
        address indexed collateralType,
        address indexed liquidator,
        uint256 debtRepaid,
        uint256 collateralSeized
    );
    event DSRJoined(address indexed user, uint256 amount);
    event DSRExited(address indexed user, uint256 amount);

    constructor(address _dai) {
        dai = DAI(_dai);
        owner = msg.sender;
    }

    modifier onlyOwner() {
        require(msg.sender == owner, "Not owner");
        _;
    }

    /**
     * @dev 添加抵押品类型
     */
    function addCollateral(
        address collateralType,
        uint256 liquidationRatio,
        uint256 stabilityFee,
        uint256 debtCeiling,
        uint256 initialPrice
    ) external onlyOwner {
        require(!collaterals[collateralType].isActive, "Collateral already exists");
        require(liquidationRatio >= 100, "Invalid liquidation ratio");

        collaterals[collateralType] = Collateral({
            totalDeposited: 0,
            totalDebt: 0,
            liquidationRatio: liquidationRatio,
            stabilityFee: stabilityFee,
            debtCeiling: debtCeiling,
            price: initialPrice,
            isActive: true
        });
    }

    /**
     * @dev 更新抵押品价格(预言机)
     */
    function updatePrice(address collateralType, uint256 newPrice) external onlyOwner {
        require(collaterals[collateralType].isActive, "Collateral not active");
        collaterals[collateralType].price = newPrice;
    }

    /**
     * @dev 存入抵押品
     */
    function depositCollateral(address collateralType, uint256 amount) external {
        require(collaterals[collateralType].isActive, "Collateral not active");
        require(amount > 0, "Amount must be positive");

        // 转入抵押品
        IERC20(collateralType).transferFrom(msg.sender, address(this), amount);

        Vault storage vault = vaults[msg.sender][collateralType];

        if (vault.collateral == 0) {
            emit VaultOpened(msg.sender, collateralType);
        }

        vault.collateral += amount;
        collaterals[collateralType].totalDeposited += amount;

        emit CollateralDeposited(msg.sender, collateralType, amount);
    }

    /**
     * @dev 提取抵押品
     */
    function withdrawCollateral(address collateralType, uint256 amount) external {
        Vault storage vault = vaults[msg.sender][collateralType];
        require(vault.collateral >= amount, "Insufficient collateral");

        // 更新累计费用
        _updateVault(msg.sender, collateralType);

        vault.collateral -= amount;

        // 检查抵押率
        require(_isVaultSafe(msg.sender, collateralType), "Vault would be unsafe");

        collaterals[collateralType].totalDeposited -= amount;

        // 转出抵押品
        IERC20(collateralType).transfer(msg.sender, amount);

        emit CollateralWithdrawn(msg.sender, collateralType, amount);
    }

    /**
     * @dev 生成DAI
     */
    function mintDAI(address collateralType, uint256 amount) external {
        require(amount > 0, "Amount must be positive");

        Collateral storage collateral = collaterals[collateralType];
        require(collateral.isActive, "Collateral not active");

        // 更新累计费用
        _updateVault(msg.sender, collateralType);

        Vault storage vault = vaults[msg.sender][collateralType];
        vault.debt += amount;

        // 检查债务上限
        require(
            collateral.totalDebt + amount <= collateral.debtCeiling,
            "Debt ceiling reached"
        );

        // 检查抵押率
        require(_isVaultSafe(msg.sender, collateralType), "Insufficient collateral");

        collateral.totalDebt += amount;

        // 铸造DAI
        dai.mint(msg.sender, amount);

        emit DAIMinted(msg.sender, collateralType, amount);
    }

    /**
     * @dev 偿还DAI
     */
    function repayDAI(address collateralType, uint256 amount) external {
        Vault storage vault = vaults[msg.sender][collateralType];

        // 更新累计费用
        _updateVault(msg.sender, collateralType);

        uint256 totalDebt = vault.debt + vault.accumulatedFee;
        uint256 repayAmount = amount > totalDebt ? totalDebt : amount;

        // 销毁DAI
        dai.burn(msg.sender, repayAmount);

        // 先偿还费用,再偿还本金
        if (repayAmount >= vault.accumulatedFee) {
            repayAmount -= vault.accumulatedFee;
            vault.accumulatedFee = 0;
            vault.debt -= repayAmount;
        } else {
            vault.accumulatedFee -= repayAmount;
        }

        collaterals[collateralType].totalDebt -= repayAmount;

        emit DAIRepaid(msg.sender, collateralType, repayAmount);
    }

    /**
     * @dev 清算金库
     */
    function liquidate(address user, address collateralType) external {
        Vault storage vault = vaults[user][collateralType];
        require(vault.debt > 0, "No debt to liquidate");

        // 更新累计费用
        _updateVault(user, collateralType);

        // 检查是否可以清算
        require(!_isVaultSafe(user, collateralType), "Vault is safe");

        Collateral storage collateral = collaterals[collateralType];
        uint256 totalDebt = vault.debt + vault.accumulatedFee;

        // 计算清算金额(最多50%)
        uint256 halfDebt = totalDebt / 2;

        // 计算需要的抵押品(含惩罚)
        uint256 collateralValue = (halfDebt * LIQUIDATION_PENALTY * 1e18) / (collateral.price * 100);
        uint256 collateralToSeize = collateralValue > vault.collateral ? vault.collateral : collateralValue;

        // 计算实际偿还的债务
        uint256 debtRepaid = (collateralToSeize * collateral.price * 100) / (LIQUIDATION_PENALTY * 1e18);

        // 转入DAI
        dai.burn(msg.sender, debtRepaid);

        // 更新金库
        vault.collateral -= collateralToSeize;
        if (debtRepaid >= vault.accumulatedFee) {
            debtRepaid -= vault.accumulatedFee;
            vault.accumulatedFee = 0;
            vault.debt -= debtRepaid;
        } else {
            vault.accumulatedFee -= debtRepaid;
        }

        collateral.totalDebt -= debtRepaid;
        collateral.totalDeposited -= collateralToSeize;

        // 转出抵押品给清算人
        IERC20(collateralType).transfer(msg.sender, collateralToSeize);

        emit VaultLiquidated(user, collateralType, msg.sender, debtRepaid, collateralToSeize);
    }

    /**
     * @dev 加入DSR(DAI储蓄)
     */
    function joinDSR(uint256 amount) external {
        require(amount > 0, "Amount must be positive");

        // 转入DAI
        dai.burn(msg.sender, amount);

        // 计算之前的利息
        if (dsrBalance[msg.sender] > 0) {
            uint256 interest = _calculateDSRInterest(msg.sender);
            dsrBalance[msg.sender] += interest;
        }

        dsrBalance[msg.sender] += amount;
        dsrTimestamp[msg.sender] = block.timestamp;

        emit DSRJoined(msg.sender, amount);
    }

    /**
     * @dev 退出DSR
     */
    function exitDSR(uint256 amount) external {
        uint256 interest = _calculateDSRInterest(msg.sender);
        uint256 totalBalance = dsrBalance[msg.sender] + interest;

        require(amount <= totalBalance, "Insufficient DSR balance");

        dsrBalance[msg.sender] = totalBalance - amount;
        dsrTimestamp[msg.sender] = block.timestamp;

        // 铸造DAI(本金+利息)
        dai.mint(msg.sender, amount);

        emit DSRExited(msg.sender, amount);
    }

    /**
     * @dev 更新金库(计算累计费用)
     */
    function _updateVault(address user, address collateralType) internal {
        Vault storage vault = vaults[user][collateralType];
        if (vault.debt == 0) {
            return;
        }

        Collateral storage collateral = collaterals[collateralType];
        uint256 timeElapsed = block.timestamp - vault.lastUpdate;

        if (timeElapsed > 0) {
            // 计算稳定费(简化为线性)
            uint256 fee = (vault.debt * collateral.stabilityFee * timeElapsed) / (365 days * 100);
            vault.accumulatedFee += fee;
            vault.lastUpdate = block.timestamp;
        }
    }

    /**
     * @dev 检查金库是否安全
     */
    function _isVaultSafe(address user, address collateralType) internal view returns (bool) {
        Vault storage vault = vaults[user][collateralType];
        if (vault.debt == 0) {
            return true;
        }

        Collateral storage collateral = collaterals[collateralType];

        // 抵押品价值
        uint256 collateralValue = (vault.collateral * collateral.price) / 1e18;

        // 总债务(包含费用)
        uint256 totalDebt = vault.debt + vault.accumulatedFee;

        // 最小抵押品价值 = 债务 * 清算比率 / 100
        uint256 minCollateralValue = (totalDebt * collateral.liquidationRatio) / 100;

        return collateralValue >= minCollateralValue;
    }

    /**
     * @dev 计算抵押率
     */
    function getCollateralizationRatio(address user, address collateralType)
        external
        view
        returns (uint256)
    {
        Vault storage vault = vaults[user][collateralType];
        if (vault.debt == 0) {
            return type(uint256).max;
        }

        Collateral storage collateral = collaterals[collateralType];

        uint256 collateralValue = (vault.collateral * collateral.price) / 1e18;
        uint256 totalDebt = vault.debt + vault.accumulatedFee;

        return (collateralValue * 100) / totalDebt;
    }

    /**
     * @dev 计算DSR利息
     */
    function _calculateDSRInterest(address user) internal view returns (uint256) {
        if (dsrBalance[user] == 0 || dsr == 0) {
            return 0;
        }

        uint256 timeElapsed = block.timestamp - dsrTimestamp[user];
        return (dsrBalance[user] * dsr * timeElapsed) / (365 days * 100);
    }

    /**
     * @dev 获取金库信息
     */
    function getVaultInfo(address user, address collateralType)
        external
        view
        returns (
            uint256 collateralAmount,
            uint256 debtAmount,
            uint256 accumulatedFee,
            uint256 collateralizationRatio,
            bool isSafe
        )
    {
        Vault storage vault = vaults[user][collateralType];
        collateralAmount = vault.collateral;
        debtAmount = vault.debt;
        accumulatedFee = vault.accumulatedFee;

        if (vault.debt > 0) {
            Collateral storage collateral = collaterals[collateralType];
            uint256 collateralValue = (vault.collateral * collateral.price) / 1e18;
            uint256 totalDebt = vault.debt + vault.accumulatedFee;
            collateralizationRatio = (collateralValue * 100) / totalDebt;
        } else {
            collateralizationRatio = type(uint256).max;
        }

        isSafe = _isVaultSafe(user, collateralType);
    }
}

第四部分:算法稳定币

4.1 算法稳定币原理

算法稳定币通过算法调整供应量来维持价格稳定,无需或仅需部分抵押。

4.1.1 常见机制

Rebase机制(如AMPL):

  • 价格高于1美元:增加所有人的余额
  • 价格低于1美元:减少所有人的余额

双代币模型(如Luna/UST):

  • 稳定币和治理代币可互换
  • 通过套利维持价格

部分抵押(如FRAX):

  • 部分由抵押品支持
  • 部分由算法控制

4.2 Rebase代币实现

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

/**
 * @title RebaseToken
 * @dev 弹性供应代币(类似AMPL)
 */
contract RebaseToken {
    string public constant name = "Rebase Token";
    string public constant symbol = "REBASE";
    uint8 public constant decimals = 18;

    // 总Gons(内部单位)
    uint256 private constant MAX_UINT256 = type(uint256).max;
    uint256 private constant INITIAL_FRAGMENTS_SUPPLY = 50 * 10**6 * 10**decimals;
    uint256 private constant TOTAL_GONS = MAX_UINT256 - (MAX_UINT256 % INITIAL_FRAGMENTS_SUPPLY);

    // 总供应量(fragments)
    uint256 private _totalSupply;

    // Gons余额
    mapping(address => uint256) private _gonBalances;

    // 授权
    mapping(address => mapping(address => uint256)) private _allowedFragments;

    // Gons per fragment
    uint256 private _gonsPerFragment;

    // 预言机和rebase控制
    address public oracle;
    address public monetaryPolicy;

    // 价格目标
    uint256 public constant TARGET_PRICE = 1e18; // $1

    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(address indexed owner, address indexed spender, uint256 value);
    event LogRebase(uint256 indexed epoch, uint256 totalSupply);

    modifier onlyMonetaryPolicy() {
        require(msg.sender == monetaryPolicy, "Not authorized");
        _;
    }

    constructor(address _oracle, address _monetaryPolicy) {
        oracle = _oracle;
        monetaryPolicy = _monetaryPolicy;

        _totalSupply = INITIAL_FRAGMENTS_SUPPLY;
        _gonsPerFragment = TOTAL_GONS / _totalSupply;

        _gonBalances[msg.sender] = TOTAL_GONS;
        emit Transfer(address(0), msg.sender, _totalSupply);
    }

    /**
     * @dev Rebase函数
     * @param supplyDelta 供应量变化(正数增加,负数减少)
     */
    function rebase(uint256 epoch, int256 supplyDelta) external onlyMonetaryPolicy returns (uint256) {
        if (supplyDelta == 0) {
            emit LogRebase(epoch, _totalSupply);
            return _totalSupply;
        }

        if (supplyDelta < 0) {
            _totalSupply = _totalSupply - uint256(-supplyDelta);
        } else {
            _totalSupply = _totalSupply + uint256(supplyDelta);
        }

        if (_totalSupply > MAX_UINT256 / _gonsPerFragment) {
            _totalSupply = MAX_UINT256 / _gonsPerFragment;
        }

        _gonsPerFragment = TOTAL_GONS / _totalSupply;

        emit LogRebase(epoch, _totalSupply);
        return _totalSupply;
    }

    /**
     * @dev 总供应量
     */
    function totalSupply() external view returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev 余额
     */
    function balanceOf(address account) external view returns (uint256) {
        return _gonBalances[account] / _gonsPerFragment;
    }

    /**
     * @dev 转账
     */
    function transfer(address to, uint256 value) external returns (bool) {
        uint256 gonValue = value * _gonsPerFragment;

        _gonBalances[msg.sender] -= gonValue;
        _gonBalances[to] += gonValue;

        emit Transfer(msg.sender, to, value);
        return true;
    }

    /**
     * @dev 授权
     */
    function approve(address spender, uint256 value) external returns (bool) {
        _allowedFragments[msg.sender][spender] = value;
        emit Approval(msg.sender, spender, value);
        return true;
    }

    /**
     * @dev 授权转账
     */
    function transferFrom(
        address from,
        address to,
        uint256 value
    ) external returns (bool) {
        _allowedFragments[from][msg.sender] -= value;

        uint256 gonValue = value * _gonsPerFragment;
        _gonBalances[from] -= gonValue;
        _gonBalances[to] += gonValue;

        emit Transfer(from, to, value);
        return true;
    }

    /**
     * @dev 授权额度
     */
    function allowance(address owner_, address spender) external view returns (uint256) {
        return _allowedFragments[owner_][spender];
    }
}

/**
 * @title MonetaryPolicy
 * @dev Rebase策略合约
 */
contract MonetaryPolicy {
    RebaseToken public token;
    address public oracle;
    uint256 public rebaseLag = 10; // rebase平滑系数

    uint256 public epoch = 0;
    uint256 public lastRebaseTime;
    uint256 public rebaseInterval = 24 hours;

    event LogRebase(
        uint256 indexed epoch,
        uint256 marketPrice,
        uint256 targetPrice,
        int256 supplyDelta,
        uint256 timestamp
    );

    constructor(address _token, address _oracle) {
        token = RebaseToken(_token);
        oracle = _oracle;
        lastRebaseTime = block.timestamp;
    }

    /**
     * @dev 执行rebase
     */
    function rebase() external {
        require(block.timestamp >= lastRebaseTime + rebaseInterval, "Too soon");

        epoch++;
        lastRebaseTime = block.timestamp;

        // 从预言机获取价格
        uint256 marketPrice = getPrice();
        uint256 targetPrice = token.TARGET_PRICE();

        if (marketPrice == targetPrice) {
            emit LogRebase(epoch, marketPrice, targetPrice, 0, block.timestamp);
            return;
        }

        // 计算供应量变化
        int256 supplyDelta = computeSupplyDelta(marketPrice, targetPrice);

        // 执行rebase
        token.rebase(epoch, supplyDelta);

        emit LogRebase(epoch, marketPrice, targetPrice, supplyDelta, block.timestamp);
    }

    /**
     * @dev 计算供应量变化
     */
    function computeSupplyDelta(uint256 marketPrice, uint256 targetPrice)
        internal
        view
        returns (int256)
    {
        int256 targetRate = int256(targetPrice);
        int256 marketRate = int256(marketPrice);

        int256 priceDelta = marketRate - targetRate;

        // supplyDelta = totalSupply * (priceDelta / targetPrice) / rebaseLag
        int256 totalSupply = int256(token.totalSupply());
        int256 supplyDelta = (totalSupply * priceDelta) / targetRate / int256(rebaseLag);

        return supplyDelta;
    }

    /**
     * @dev 获取价格(简化,实际应从预言机获取)
     */
    function getPrice() public view returns (uint256) {
        // 这里应该从实际的预言机获取价格
        // 简化起见,返回固定值
        return 1e18;
    }
}

第五部分:稳定币风险分析

5.1 各类稳定币的风险

5.1.1 法币抵押型稳定币

风险:

  1. 中心化风险:依赖发行方的信用
  2. 托管风险:储备金安全
  3. 监管风险:可能被冻结或限制
  4. 透明度风险:储备金审计不透明

案例:USDT曾因储备金透明度问题引发争议

5.1.2 加密抵押型稳定币

风险:

  1. 价格波动风险:抵押品价格剧烈波动
  2. 清算风险:市场崩盘时清算系统可能失效
  3. 预言机风险:价格喂价被操纵
  4. 资本效率低:需要超额抵押

案例:2020年3月12日,ETH价格暴跌,导致大量MakerDAO金库被清算

5.1.3 算法稳定币

风险:

  1. 死亡螺旋:失去锚定后难以恢复
  2. 信心风险:完全依赖市场信心
  3. 复杂性风险:机制复杂,难以理解
  4. 历史记录差:多个项目已经失败

案例:Terra/UST在2022年5月崩盘,损失超过400亿美元

5.2 稳定币监控指标

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

/**
 * @title StablecoinMonitor
 * @dev 稳定币健康度监控
 */
contract StablecoinMonitor {
    struct HealthMetrics {
        uint256 price; // 当前价格
        uint256 marketCap; // 市值
        uint256 collateralRatio; // 抵押率
        uint256 liquidityDepth; // 流动性深度
        uint256 peg Deviation; // 锚定偏离度
        uint256 timestamp;
    }

    mapping(address => HealthMetrics[]) public metricsHistory;

    event MetricsUpdated(address indexed stablecoin, uint256 timestamp);
    event AlertTriggered(address indexed stablecoin, string alertType, uint256 value);

    // 警报阈值
    uint256 public constant PRICE_DEVIATION_THRESHOLD = 5e16; // 5%
    uint256 public constant MIN_COLLATERAL_RATIO = 120e16; // 120%

    /**
     * @dev 更新指标
     */
    function updateMetrics(
        address stablecoin,
        uint256 price,
        uint256 marketCap,
        uint256 collateralRatio,
        uint256 liquidityDepth
    ) external {
        uint256 pegDeviation = price > 1e18 ? price - 1e18 : 1e18 - price;

        HealthMetrics memory metrics = HealthMetrics({
            price: price,
            marketCap: marketCap,
            collateralRatio: collateralRatio,
            liquidityDepth: liquidityDepth,
            pegDeviation: pegDeviation,
            timestamp: block.timestamp
        });

        metricsHistory[stablecoin].push(metrics);

        // 检查警报
        if (pegDeviation > PRICE_DEVIATION_THRESHOLD) {
            emit AlertTriggered(stablecoin, "PRICE_DEVIATION", pegDeviation);
        }

        if (collateralRatio < MIN_COLLATERAL_RATIO) {
            emit AlertTriggered(stablecoin, "LOW_COLLATERAL", collateralRatio);
        }

        emit MetricsUpdated(stablecoin, block.timestamp);
    }

    /**
     * @dev 获取最新指标
     */
    function getLatestMetrics(address stablecoin) external view returns (HealthMetrics memory) {
        HealthMetrics[] storage history = metricsHistory[stablecoin];
        require(history.length > 0, "No metrics available");
        return history[history.length - 1];
    }

    /**
     * @dev 获取历史指标
     */
    function getMetricsHistory(address stablecoin, uint256 count)
        external
        view
        returns (HealthMetrics[] memory)
    {
        HealthMetrics[] storage history = metricsHistory[stablecoin];
        uint256 length = history.length;
        uint256 returnCount = count > length ? length : count;

        HealthMetrics[] memory result = new HealthMetrics[](returnCount);

        for (uint256 i = 0; i < returnCount; i++) {
            result[i] = history[length - returnCount + i];
        }

        return result;
    }
}
Prev
07-DeFi核心协议-借贷协议
Next
NFT与元宇宙