分层收益模型实战:一套代码打通理论到落地全流程

  • 木西
  • 发布于 2小时前
  • 阅读 19

前言本文系统梳理了收益分层交易的相关知识体系,具体涵盖其核心定义、核心能力、解决的行业痛点、典型行业应用场景、核心优劣势,以及关键认知要点;在代码落地层面,将基于HardhatV3开发框架,结合OpenZeppelinV5库与Solidity0.8.24及以上版本,完整实现该业

前言

本文系统梳理了收益分层交易的相关知识体系,具体涵盖其核心定义、核心能力、解决的行业痛点、典型行业应用场景、核心优劣势,以及关键认知要点;在代码落地层面,将基于 Hardhat V3 开发框架,结合 OpenZeppelin V5 库与 Solidity 0.8.24 及以上版本,完整实现该业务从开发、测试到部署的全流程。

一、是什么

DeFi领域基于区块链的结构化金融合约,核心是按风险、兑付优先级拆分资产池为不同层级份额,自动分配交易收益、亏损与清算,全程去中心化、无人工干预,底层依托公链与预言机实现闭环。

核心分层:优先级(低风险低收益,优先兑付)、劣后级(高风险高收益,兜底亏损)、夹层(风险收益居中,可选设)。

二、能做什么与解决的问题

(一)核心能力

  • 拆分风险收益,匹配不同偏好投资者;
  • 链上自动执行分配、清算,结果可审计;
  • 分层份额代币化,支持交易、质押流通;
  • 设定风险阈值,管控极端行情风险。

(二)核心痛点

  • 解决投资者风险偏好与产品不匹配问题;
  • 规避传统结构化产品中心化、不透明、门槛高的弊端;
  • 提升链上资产利用率,整合闲置资金与交易需求;
  • 消除收益分配纠纷,实现透明化执行。

三、行业应用

主要落地于DeFi赛道,核心场景包括:

  1. 去中心化借贷:分层分配借贷利息,平衡风险与收益;
  2. 收益聚合器:拆分多策略收益池,适配不同风险需求;
  3. 衍生品与杠杆交易:保证金池分层,提供流动性与风险备付;
  4. NFTFi:拆分NFT收益池,覆盖租赁、抵押等收益;
  5. 实体资产通证化:分层分配实体资产现金流,降低参与门槛。

四、优劣势

(一)优势

  • 透明可审计,信任成本低,无暗箱操作;
  • 自动执行无偏差,7×24小时运行;
  • 精准匹配风险收益,用户覆盖面广、门槛低;
  • 提升资产效率,支持份额组合金融化。

(二)劣势

  • 合约逻辑复杂,存在代码漏洞与审计风险;
  • 专业门槛高,普通用户易产生认知误区;
  • 极端行情下有连环清算、预言机依赖风险;
  • 监管模糊,流动性碎片化,链上性能受限。

五、关键认知

  1. 非保本合约,优先层仅相对优先兑付;
  2. 核心价值是风险分层,而非单纯收益分配;
  3. 目前处于DeFi小众创新阶段,尚未大规模普及。

    智能合约开发、测试、部署

    智能合约

    • 代币合约
      
      // SPDX-License-Identifier: MIT
      // Compatible with OpenZeppelin Contracts ^5.5.0
      pragma solidity ^0.8.24;

import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import {ERC20Burnable} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol"; import {ERC20Permit} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol"; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";

contract BoykaYuriToken is ERC20, ERC20Burnable, Ownable, ERC20Permit { constructor(address recipient, address initialOwner) ERC20("MyToken", "MTK") Ownable(initialOwner) ERC20Permit("MyToken") { _mint(recipient, 1000000 * 10 ** decimals()); } function mint(address to, uint256 amount) public onlyOwner { _mint(to, amount); } }

* **收益分层交易合约**
```js
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";

// 模拟 PT 和 YT 代币
contract YieldToken is ERC20 {
    constructor(string memory name, string memory symbol) ERC20(name, symbol) {}
    function mint(address to, uint256 amount) external { _mint(to, amount); }
    function burn(address from, uint256 amount) external { _burn(from, amount); }
}

contract YieldSplitVault is ReentrancyGuard {
    IERC20 public immutable yieldBearingToken; // 生息代币 (如 stETH)
    YieldToken public pt; // 本金代币
    YieldToken public yt; // 收益代币

    uint256 public totalUnderlying; // 记录初始存入的总本金
    uint256 public expiry;          // 到期时间

    constructor(address _ybt, uint256 _duration) {
        yieldBearingToken = IERC20(_ybt);
        expiry = block.timestamp + _duration;
        pt = new YieldToken("Principal Token", "PT");
        yt = new YieldToken("Yield Token", "YT");
    }

    // 存入本金,铸造 PT 和 YT
    function deposit(uint256 amount) external nonReentrant {
        require(block.timestamp < expiry, "Expired");

        yieldBearingToken.transferFrom(msg.sender, address(this), amount);

        pt.mint(msg.sender, amount);
        yt.mint(msg.sender, amount);

        totalUnderlying += amount;
    }

    // 只有 YT 持有者可以随时提取当前产生的利息
    function collectInterest() external nonReentrant {
        uint256 currentBalance = yieldBearingToken.balanceOf(address(this));
        // 利息 = 当前总余额 - 锁定的本金
        uint256 interest = currentBalance > totalUnderlying ? currentBalance - totalUnderlying : 0;
        require(interest > 0, "No interest");

        // 简化的逻辑:根据调用者的 YT 持股比例分利(此处演示直接全取)
        yieldBearingToken.transfer(msg.sender, interest);
    }

    // 到期后,销毁 PT 取回本金
    function redeem(uint256 amount) external nonReentrant {
        require(block.timestamp >= expiry, "Not expired yet");

        pt.burn(msg.sender, amount);
        totalUnderlying -= amount;
        yieldBearingToken.transfer(msg.sender, amount);
    }
}

测试脚本

测试用例:

  • 用户存入资产应获得等额的 PT 和 YT
  • 利息产生后,YT 持有者应能提取收益
  • 未到期前无法赎回本金
    
    import assert from "node:assert/strict";
    import { describe, it, beforeEach } from "node:test";
    import { parseEther, formatEther } from 'viem';
    import { network } from "hardhat";

describe("YieldSplitVault 收益分层测试", function () { let publicClient: any, vault: any, stETH: any; let owner: any, user: any;

beforeEach(async function () { const { viem } = await network.connect(); publicClient = await viem.getPublicClient(); [owner, user] = await viem.getWalletClients();

// 1. 部署一个模拟的 stETH (生息代币)
stETH = await viem.deployContract("BoykaYuriToken", [owner.account.address, owner.account.address]);

// 2. 部署分层金库 (有效期 1 小时)
vault = await viem.deployContract("YieldSplitVault", [stETH.address, 3600n]);

// 给用户一些 stETH
await stETH.write.transfer([user.account.address, parseEther("100")], { account: owner.account });

});

it("用户存入资产应获得等额的 PT 和 YT", async function () { const depositAmount = parseEther("10");

// 授权并存入
await stETH.write.approve([vault.address, depositAmount], { account: user.account });
await vault.write.deposit([depositAmount], { account: user.account });

// 获取 PT 和 YT 地址
const ptAddress = await vault.read.pt();
const ytAddress = await vault.read.yt();

// 检查余额
const ptBalance = await publicClient.readContract({
    address: ptAddress,
    abi: [{ name: "balanceOf", type: "function", inputs: [{ type: "address" }], outputs: [{ type: "uint256" }] }],
    functionName: "balanceOf",
    args: [user.account.address]
});

assert.equal(ptBalance, depositAmount, "PT 铸造数量错误");
console.log("✅ 成功铸造 PT 和 YT");

});

it("利息产生后,YT 持有者应能提取收益", async function () { const depositAmount = parseEther("10"); await stETH.write.approve([vault.address, depositAmount], { account: user.account }); await vault.write.deposit([depositAmount], { account: user.account });

// 模拟产生了 1 ETH 的利息 (直接向金库转账)
await stETH.write.transfer([vault.address, parseEther("1")], { account: owner.account });

const balanceBefore = await stETH.read.balanceOf([user.account.address]);
await vault.write.collectInterest({ account: user.account });
const balanceAfter = await stETH.read.balanceOf([user.account.address]);

assert.ok(balanceAfter > balanceBefore, "未成功提取利息");
console.log(`✅ 提取利息成功: ${formatEther(balanceAfter - balanceBefore)} stETH`);

});

it("未到期前无法赎回本金", async function () { const depositAmount = parseEther("10"); await stETH.write.approve([vault.address, depositAmount], { account: user.account }); await vault.write.deposit([depositAmount], { account: user.account });

// 尝试提前赎回
await assert.rejects(
    vault.write.redeem([depositAmount], { account: user.account }),
    /Not expired yet/,
    "不应允许提前赎回"
);

}); });

### 部署脚本
```js
// scripts/deploy.js
import { network, artifacts } from "hardhat";
import { parseUnits } from "viem";
async function main() {
  // 获取客户端(hardhat-viem 插件会自动处理网络连接)
   const { viem } = await network.connect({ network: network.name });//指定网络进行链接

  const [deployer, user1, user2] = await viem.getWalletClients();
  const publicClient = await viem.getPublicClient();
  const deployerAddress = deployer.account.address;
  console.log("部署者地址:", deployerAddress);

  // 1. 获取 ABI 和 Bytecode
  const BoykaYuriTokenArtifact = await artifacts.readArtifact("BoykaYuriToken");
  const YieldSplitVaultArtifact = await artifacts.readArtifact("YieldSplitVault");

  // 2. 部署 BoykaYuriToken 合约
  const BoykaYuriTokenHash = await deployer.deployContract({
    abi: BoykaYuriTokenArtifact.abi,
    bytecode: BoykaYuriTokenArtifact.bytecode,
    args: [deployerAddress, deployerAddress],
  });
  const BoykaYuriToken= await publicClient.waitForTransactionReceipt({ hash: BoykaYuriTokenHash });
  console.log("BoykaYuriToken 地址:", BoykaYuriToken.contractAddress);
  // 3. 部署 YieldSplitVault 合约
  const YieldSplitVaultHash = await deployer.deployContract({
    abi: YieldSplitVaultArtifact.abi,
    bytecode: YieldSplitVaultArtifact.bytecode,
    args: [BoykaYuriToken.contractAddress,3600n],
  });
  const YieldSplitVault= await publicClient.waitForTransactionReceipt({ hash: YieldSplitVaultHash });
  console.log("YieldSplitVault 地址:", YieldSplitVault.contractAddress);

}

main().catch((error) => {
  console.error(error);
  process.exit(1);
});

结语

至此,我们已完整实现收益分层交易从理论认知到代码实践的全流程落地,覆盖开发、测试与部署各核心环节。

点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
木西
木西
0x5D5C...2dD7
江湖只有他的大名,没有他的介绍。