This commit is contained in:
2025-12-18 13:07:35 +08:00
commit 76b7f838db
271 changed files with 88812 additions and 0 deletions

View File

@@ -0,0 +1,87 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
/**
* @title USDY Token
* @notice 统一计价代币
* @dev 只有授权的Vault可以铸造和销毁UUPS可升级合约
*/
contract USDY is Initializable, ERC20Upgradeable, OwnableUpgradeable, UUPSUpgradeable {
error Forbidden();
error InvalidVault();
mapping(address => bool) public vaults;
event VaultAdded(address indexed vault);
event VaultRemoved(address indexed vault);
modifier onlyVault() {
if (!vaults[msg.sender]) revert Forbidden();
_;
}
/**
* @notice 初始化合约
*/
function initialize() external initializer {
__ERC20_init("YT USD", "USDY");
__Ownable_init(msg.sender);
__UUPSUpgradeable_init();
}
/**
* @notice 授权升级仅owner可调用
* @param newImplementation 新实现合约地址
*/
function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}
/**
* @notice 添加授权的Vault地址
* @param _vault Vault合约地址
*/
function addVault(address _vault) external onlyOwner {
if (_vault == address(0)) revert InvalidVault();
vaults[_vault] = true;
emit VaultAdded(_vault);
}
/**
* @notice 移除授权的Vault地址
* @param _vault Vault合约地址
*/
function removeVault(address _vault) external onlyOwner {
vaults[_vault] = false;
emit VaultRemoved(_vault);
}
/**
* @notice 铸造USDY代币
* @param _account 接收地址
* @param _amount 铸造数量
*/
function mint(address _account, uint256 _amount) external onlyVault {
_mint(_account, _amount);
}
/**
* @notice 销毁USDY代币
* @param _account 销毁地址
* @param _amount 销毁数量
*/
function burn(address _account, uint256 _amount) external onlyVault {
_burn(_account, _amount);
}
/**
* @dev 预留存储空间,用于未来升级时添加新的状态变量
* 50个slot = 50 * 32 bytes = 1600 bytes
*/
uint256[50] private __gap;
}

View File

@@ -0,0 +1,54 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
/**
* @title WUSD
* @notice Wrapped USD - 简单的ERC20代币
*/
contract WUSD is Initializable, ERC20Upgradeable, UUPSUpgradeable, OwnableUpgradeable {
/**
* @notice 初始化合约
* @param _name 代币名称
* @param _symbol 代币符号
*/
function initialize(string memory _name, string memory _symbol) external initializer {
__ERC20_init(_name, _symbol);
__UUPSUpgradeable_init();
__Ownable_init(msg.sender);
}
/**
* @notice 授权升级仅owner可调用
* @param newImplementation 新实现合约地址
*/
function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}
/**
* @notice 铸造代币
* @param _to 接收地址
* @param _amount 铸造数量
*/
function mint(address _to, uint256 _amount) external onlyOwner {
_mint(_to, _amount);
}
/**
* @notice 销毁代币
* @param _from 销毁地址
* @param _amount 销毁数量
*/
function burn(address _from, uint256 _amount) external onlyOwner {
_burn(_from, _amount);
}
/**
* @dev 预留存储空间,用于未来升级时添加新的状态变量
*/
uint256[50] private __gap;
}

View File

@@ -0,0 +1,78 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
/**
* @title YTLPToken
* @notice LP代币代表用户在池子中的份额
* @dev 只有授权的MinterYTPoolManager可以铸造和销毁UUPS可升级合约
*/
contract YTLPToken is Initializable, ERC20Upgradeable, OwnableUpgradeable, UUPSUpgradeable {
error NotMinter();
error InvalidMinter();
mapping(address => bool) public isMinter;
event MinterSet(address indexed minter, bool isActive);
/**
* @notice 初始化合约
*/
function initialize() external initializer {
__ERC20_init("YT Liquidity Provider", "ytLP");
__Ownable_init(msg.sender);
__UUPSUpgradeable_init();
}
/**
* @notice 授权升级仅owner可调用
* @param newImplementation 新实现合约地址
*/
function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}
modifier onlyMinter() {
if (!isMinter[msg.sender]) revert NotMinter();
_;
}
/**
* @notice 设置铸造权限
* @param _minter 铸造者地址
* @param _isActive 是否激活
*/
function setMinter(address _minter, bool _isActive) external onlyOwner {
if (_minter == address(0)) revert InvalidMinter();
isMinter[_minter] = _isActive;
emit MinterSet(_minter, _isActive);
}
/**
* @notice 铸造ytLP代币
* @param _to 接收地址
* @param _amount 铸造数量
*/
function mint(address _to, uint256 _amount) external onlyMinter {
_mint(_to, _amount);
}
/**
* @notice 销毁ytLP代币
* @param _from 销毁地址
* @param _amount 销毁数量
*/
function burn(address _from, uint256 _amount) external onlyMinter {
_burn(_from, _amount);
}
/**
* @dev 预留存储空间,用于未来升级时添加新的状态变量
* 50个slot = 50 * 32 bytes = 1600 bytes
*/
uint256[50] private __gap;
}

View File

@@ -0,0 +1,161 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
/**
* @title YTToken
* @notice YT代币示例实现Yield Token
* @dev 展示如何实现价格接口供YTPriceFeed读取
*/
contract YTToken is ERC20, Ownable {
error NotUpdater();
error InvalidUpdater();
error IntervalTooLong();
error UpdateTooFrequent();
error InvalidYield();
error InvalidAmount();
error InsufficientAssets();
uint256 public constant PRICE_PRECISION = 10 ** 30;
uint256 public totalAssets;
uint256 public accumulatedYield;
// 价格变量
uint256 public assetPrice;
uint256 public lastPriceUpdate;
// 价格更新控制
address public priceUpdater;
uint256 public minUpdateInterval = 5 minutes; // 最小更新间隔
event PriceUpdated(uint256 oldPrice, uint256 newPrice, uint256 timestamp);
event YieldAccumulated(uint256 amount, uint256 timestamp);
event PriceUpdaterSet(address indexed updater);
event MinUpdateIntervalSet(uint256 interval);
modifier onlyPriceUpdater() {
if (msg.sender != priceUpdater && msg.sender != owner()) revert NotUpdater();
_;
}
constructor(
string memory name,
string memory symbol,
address _priceUpdater
) ERC20(name, symbol) Ownable(msg.sender) {
assetPrice = PRICE_PRECISION; // 初始价格为1
lastPriceUpdate = block.timestamp;
priceUpdater = _priceUpdater;
}
/**
* @notice 设置价格更新者
*/
function setPriceUpdater(address _updater) external onlyOwner {
if (_updater == address(0)) revert InvalidUpdater();
priceUpdater = _updater;
emit PriceUpdaterSet(_updater);
}
/**
* @notice 设置最小更新间隔
*/
function setMinUpdateInterval(uint256 _interval) external onlyOwner {
if (_interval > 1 hours) revert IntervalTooLong();
minUpdateInterval = _interval;
emit MinUpdateIntervalSet(_interval);
}
/**
* @notice 更新代币价格
* @dev 只能由授权的updater调用有最小时间间隔限制
*/
function updatePrice() public onlyPriceUpdater {
if (block.timestamp < lastPriceUpdate + minUpdateInterval) revert UpdateTooFrequent();
uint256 oldPrice = assetPrice;
uint256 supply = totalSupply();
if (supply == 0) {
assetPrice = PRICE_PRECISION;
} else {
uint256 totalValue = totalAssets + accumulatedYield;
// 计算每个token对应的USDC价值18位精度
uint256 usdcPerToken = totalValue * 1e18 / supply;
// 转换为30位精度的价格
assetPrice = usdcPerToken * PRICE_PRECISION / 1e18;
}
lastPriceUpdate = block.timestamp;
emit PriceUpdated(oldPrice, assetPrice, block.timestamp);
}
/**
* @notice 累积收益并更新价格
* @dev 当从收益策略中收到新收益时调用
*/
function updateYield(uint256 _newYield) external onlyPriceUpdater {
if (_newYield == 0) revert InvalidYield();
accumulatedYield += _newYield;
emit YieldAccumulated(_newYield, block.timestamp);
// 收益更新后立即更新价格
if (block.timestamp >= lastPriceUpdate + minUpdateInterval) {
uint256 oldPrice = assetPrice;
uint256 supply = totalSupply();
if (supply > 0) {
uint256 totalValue = totalAssets + accumulatedYield;
uint256 usdcPerToken = totalValue * 1e18 / supply;
assetPrice = usdcPerToken * PRICE_PRECISION / 1e18;
}
lastPriceUpdate = block.timestamp;
emit PriceUpdated(oldPrice, assetPrice, block.timestamp);
}
}
/**
* @notice 存入资产(模拟)
* @dev 实际实现中应该处理真实的USDC存款
*/
function deposit(uint256 _amount) external onlyOwner {
if (_amount == 0) revert InvalidAmount();
totalAssets += _amount;
_mint(msg.sender, _amount);
}
/**
* @notice 提取资产(模拟)
* @dev 实际实现中应该处理真实的USDC提款
*/
function withdraw(uint256 _amount) external onlyOwner {
if (_amount == 0) revert InvalidAmount();
if (totalAssets < _amount) revert InsufficientAssets();
totalAssets -= _amount;
_burn(msg.sender, _amount);
}
/**
* @notice 获取当前价格信息
*/
function getPriceInfo() external view returns (
uint256 price,
uint256 lastUpdate,
uint256 timeSinceUpdate,
uint256 totalVal
) {
price = assetPrice;
lastUpdate = lastPriceUpdate;
timeSinceUpdate = block.timestamp - lastPriceUpdate;
totalVal = totalAssets + accumulatedYield;
}
}