Files
assetxContracts/contracts/ytVault/YTAssetFactory.sol

302 lines
9.7 KiB
Solidity
Raw Permalink Normal View History

2025-12-18 13:07:35 +08:00
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
import "./YTAssetVault.sol";
contract YTAssetFactory is Initializable, UUPSUpgradeable, OwnableUpgradeable {
error InvalidAddress();
error VaultNotExists();
error InvalidHardCap();
2025-12-23 14:05:41 +08:00
/// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
_disableInitializers();
}
2025-12-18 13:07:35 +08:00
address public vaultImplementation;
address[] public allVaults;
mapping(address => bool) public isVault;
uint256 public defaultHardCap;
event VaultCreated(
address indexed vault,
address indexed manager,
string name,
string symbol,
uint256 hardCap,
uint256 index
);
event VaultImplementationUpdated(address indexed newImplementation);
event DefaultHardCapSet(uint256 newDefaultHardCap);
event HardCapSet(address indexed vault, uint256 newHardCap);
2025-12-24 16:41:26 +08:00
event PricesUpdated(address indexed vault, uint256 ytPrice);
2025-12-18 13:07:35 +08:00
event NextRedemptionTimeSet(address indexed vault, uint256 redemptionTime);
function initialize(
address _vaultImplementation,
uint256 _defaultHardCap
) external initializer {
if (_vaultImplementation == address(0)) revert InvalidAddress();
__Ownable_init(msg.sender);
__UUPSUpgradeable_init();
vaultImplementation = _vaultImplementation;
defaultHardCap = _defaultHardCap;
}
2025-12-25 13:29:35 +08:00
2025-12-18 13:07:35 +08:00
function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}
2025-12-25 13:29:35 +08:00
2025-12-18 13:07:35 +08:00
function setVaultImplementation(address _newImplementation) external onlyOwner {
if (_newImplementation == address(0)) revert InvalidAddress();
vaultImplementation = _newImplementation;
emit VaultImplementationUpdated(_newImplementation);
}
function setDefaultHardCap(uint256 _defaultHardCap) external onlyOwner {
defaultHardCap = _defaultHardCap;
emit DefaultHardCapSet(_defaultHardCap);
}
function createVault(
string memory _name,
string memory _symbol,
address _manager,
uint256 _hardCap,
2025-12-24 16:41:26 +08:00
address _usdc,
2025-12-18 13:07:35 +08:00
uint256 _redemptionTime,
2025-12-24 16:41:26 +08:00
uint256 _initialYtPrice,
address _usdcPriceFeed
2025-12-18 13:07:35 +08:00
) external onlyOwner returns (address vault) {
if (_manager == address(0)) revert InvalidAddress();
2025-12-25 13:29:35 +08:00
2025-12-18 13:07:35 +08:00
uint256 actualHardCap = _hardCap == 0 ? defaultHardCap : _hardCap;
bytes memory initData = abi.encodeWithSelector(
YTAssetVault.initialize.selector,
_name,
_symbol,
_manager,
actualHardCap,
2025-12-24 16:41:26 +08:00
_usdc,
2025-12-18 13:07:35 +08:00
_redemptionTime,
2025-12-24 16:41:26 +08:00
_initialYtPrice,
_usdcPriceFeed
2025-12-18 13:07:35 +08:00
);
vault = address(new ERC1967Proxy(vaultImplementation, initData));
allVaults.push(vault);
isVault[vault] = true;
emit VaultCreated(
vault,
_manager,
_name,
_symbol,
actualHardCap,
allVaults.length - 1
);
}
function createVaultBatch(
string[] memory _names,
string[] memory _symbols,
address[] memory _managers,
uint256[] memory _hardCaps,
2025-12-24 16:41:26 +08:00
address _usdc,
2025-12-18 13:07:35 +08:00
uint256[] memory _redemptionTimes,
2025-12-24 16:41:26 +08:00
uint256[] memory _initialYtPrices,
address _usdcPriceFeed
2025-12-29 11:09:53 +08:00
) external onlyOwner returns (address[] memory vaults) {
2025-12-18 13:07:35 +08:00
require(
_names.length == _symbols.length &&
_names.length == _managers.length &&
_names.length == _hardCaps.length &&
_names.length == _redemptionTimes.length &&
_names.length == _initialYtPrices.length,
"Length mismatch"
);
vaults = new address[](_names.length);
for (uint256 i = 0; i < _names.length; i++) {
vaults[i] = this.createVault(
_names[i],
_symbols[i],
_managers[i],
_hardCaps[i],
2025-12-24 16:41:26 +08:00
_usdc,
2025-12-18 13:07:35 +08:00
_redemptionTimes[i],
2025-12-24 16:41:26 +08:00
_initialYtPrices[i],
_usdcPriceFeed
2025-12-18 13:07:35 +08:00
);
}
}
function setHardCap(address _vault, uint256 _hardCap) external onlyOwner {
if (!isVault[_vault]) revert VaultNotExists();
YTAssetVault(_vault).setHardCap(_hardCap);
emit HardCapSet(_vault, _hardCap);
}
function setHardCapBatch(
address[] memory _vaults,
uint256[] memory _hardCaps
) external onlyOwner {
require(_vaults.length == _hardCaps.length, "Length mismatch");
for (uint256 i = 0; i < _vaults.length; i++) {
if (!isVault[_vaults[i]]) revert VaultNotExists();
YTAssetVault(_vaults[i]).setHardCap(_hardCaps[i]);
emit HardCapSet(_vaults[i], _hardCaps[i]);
}
}
function setVaultManager(address _vault, address _manager) external onlyOwner {
if (!isVault[_vault]) revert VaultNotExists();
if (_manager == address(0)) revert InvalidAddress();
YTAssetVault(_vault).setManager(_manager);
}
function setVaultNextRedemptionTime(address _vault, uint256 _nextRedemptionTime) external onlyOwner {
if (!isVault[_vault]) revert VaultNotExists();
YTAssetVault(_vault).setNextRedemptionTime(_nextRedemptionTime);
emit NextRedemptionTimeSet(_vault, _nextRedemptionTime);
}
function setVaultNextRedemptionTimeBatch(
address[] memory _vaults,
uint256 _nextRedemptionTime
) external onlyOwner {
for (uint256 i = 0; i < _vaults.length; i++) {
if (!isVault[_vaults[i]]) revert VaultNotExists();
YTAssetVault(_vaults[i]).setNextRedemptionTime(_nextRedemptionTime);
emit NextRedemptionTimeSet(_vaults[i], _nextRedemptionTime);
}
}
function pauseVault(address _vault) external onlyOwner {
if (!isVault[_vault]) revert VaultNotExists();
YTAssetVault(_vault).pause();
}
function unpauseVault(address _vault) external onlyOwner {
if (!isVault[_vault]) revert VaultNotExists();
YTAssetVault(_vault).unpause();
}
function pauseVaultBatch(address[] memory _vaults) external onlyOwner {
for (uint256 i = 0; i < _vaults.length; i++) {
if (!isVault[_vaults[i]]) revert VaultNotExists();
YTAssetVault(_vaults[i]).pause();
}
}
function unpauseVaultBatch(address[] memory _vaults) external onlyOwner {
for (uint256 i = 0; i < _vaults.length; i++) {
if (!isVault[_vaults[i]]) revert VaultNotExists();
YTAssetVault(_vaults[i]).unpause();
}
}
function updateVaultPrices(
2025-12-24 16:41:26 +08:00
address _vault,
2025-12-18 13:07:35 +08:00
uint256 _ytPrice
) external onlyOwner {
if (!isVault[_vault]) revert VaultNotExists();
2025-12-24 16:41:26 +08:00
YTAssetVault(_vault).updatePrices(_ytPrice);
emit PricesUpdated(_vault, _ytPrice);
2025-12-18 13:07:35 +08:00
}
function updateVaultPricesBatch(
address[] memory _vaults,
uint256[] memory _ytPrices
) external onlyOwner {
2025-12-24 16:41:26 +08:00
require(_vaults.length == _ytPrices.length, "Length mismatch");
2025-12-18 13:07:35 +08:00
for (uint256 i = 0; i < _vaults.length; i++) {
if (!isVault[_vaults[i]]) revert VaultNotExists();
2025-12-24 16:41:26 +08:00
YTAssetVault(_vaults[i]).updatePrices(_ytPrices[i]);
emit PricesUpdated(_vaults[i], _ytPrices[i]);
2025-12-18 13:07:35 +08:00
}
}
function upgradeVault(address _vault, address _newImplementation) external onlyOwner {
if (!isVault[_vault]) revert VaultNotExists();
if (_newImplementation == address(0)) revert InvalidAddress();
YTAssetVault(_vault).upgradeToAndCall(_newImplementation, "");
}
function upgradeVaultBatch(
address[] memory _vaults,
address _newImplementation
) external onlyOwner {
if (_newImplementation == address(0)) revert InvalidAddress();
for (uint256 i = 0; i < _vaults.length; i++) {
if (!isVault[_vaults[i]]) revert VaultNotExists();
YTAssetVault(_vaults[i]).upgradeToAndCall(_newImplementation, "");
}
}
function getVaultCount() external view returns (uint256) {
return allVaults.length;
}
function getVaults(uint256 _start, uint256 _end)
external
view
returns (address[] memory vaults)
{
require(_start < _end && _end <= allVaults.length, "Invalid range");
vaults = new address[](_end - _start);
for (uint256 i = _start; i < _end; i++) {
vaults[i - _start] = allVaults[i];
}
}
function getAllVaults() external view returns (address[] memory) {
return allVaults;
}
function getVaultInfo(address _vault) external view returns (
bool exists,
uint256 totalAssets,
uint256 idleAssets,
uint256 managedAssets,
uint256 totalSupply,
uint256 hardCap,
2025-12-24 16:41:26 +08:00
uint256 usdcPrice,
2025-12-18 13:07:35 +08:00
uint256 ytPrice,
uint256 nextRedemptionTime
) {
exists = isVault[_vault];
if (!exists) return (false, 0, 0, 0, 0, 0, 0, 0, 0);
(
totalAssets,
idleAssets,
managedAssets,
totalSupply,
hardCap,
2025-12-24 16:41:26 +08:00
usdcPrice,
2025-12-18 13:07:35 +08:00
ytPrice,
nextRedemptionTime
) = YTAssetVault(_vault).getVaultInfo();
}
uint256[50] private __gap;
2025-12-25 13:29:35 +08:00
}