add view function

This commit is contained in:
2026-03-09 10:30:50 +08:00
parent 586b04a371
commit e033cbd1c4
11 changed files with 369 additions and 13 deletions

View File

@@ -3181,7 +3181,7 @@
"label": "bool",
"numberOfBytes": "1"
},
"t_struct(InitializableStorage)119_storage": {
"t_struct(InitializableStorage)73_storage": {
"label": "struct Initializable.InitializableStorage",
"members": [
{
@@ -3199,7 +3199,7 @@
],
"numberOfBytes": "32"
},
"t_struct(ReentrancyGuardStorage)527_storage": {
"t_struct(ReentrancyGuardStorage)288_storage": {
"label": "struct ReentrancyGuardUpgradeable.ReentrancyGuardStorage",
"members": [
{
@@ -4394,6 +4394,185 @@
]
}
}
},
"dc3d954e8140fb833cc048d63ec3b0b1c2bae49df5774f288830e88ab47eea38": {
"address": "0xf4cE104E687F5d2064481cbD5B24ED52d7C324b0",
"txHash": "0x254270c14cb61720fc0be515fb41c1ce98a62c5ae6bd9505cde700dcf0b4233e",
"layout": {
"solcVersion": "0.8.28",
"storage": [
{
"label": "gov",
"offset": 0,
"slot": "0",
"type": "t_address",
"contract": "YTPoolManager",
"src": "contracts/ytLp/core/YTPoolManager.sol:40"
},
{
"label": "ytVault",
"offset": 0,
"slot": "1",
"type": "t_address",
"contract": "YTPoolManager",
"src": "contracts/ytLp/core/YTPoolManager.sol:41"
},
{
"label": "usdy",
"offset": 0,
"slot": "2",
"type": "t_address",
"contract": "YTPoolManager",
"src": "contracts/ytLp/core/YTPoolManager.sol:42"
},
{
"label": "ytLP",
"offset": 0,
"slot": "3",
"type": "t_address",
"contract": "YTPoolManager",
"src": "contracts/ytLp/core/YTPoolManager.sol:44"
},
{
"label": "cooldownDuration",
"offset": 0,
"slot": "4",
"type": "t_uint256",
"contract": "YTPoolManager",
"src": "contracts/ytLp/core/YTPoolManager.sol:45"
},
{
"label": "lastAddedAt",
"offset": 0,
"slot": "5",
"type": "t_mapping(t_address,t_uint256)",
"contract": "YTPoolManager",
"src": "contracts/ytLp/core/YTPoolManager.sol:45"
},
{
"label": "isHandler",
"offset": 0,
"slot": "6",
"type": "t_mapping(t_address,t_bool)",
"contract": "YTPoolManager",
"src": "contracts/ytLp/core/YTPoolManager.sol:47"
},
{
"label": "aumAddition",
"offset": 0,
"slot": "7",
"type": "t_uint256",
"contract": "YTPoolManager",
"src": "contracts/ytLp/core/YTPoolManager.sol:50"
},
{
"label": "aumDeduction",
"offset": 0,
"slot": "8",
"type": "t_uint256",
"contract": "YTPoolManager",
"src": "contracts/ytLp/core/YTPoolManager.sol:52"
},
{
"label": "__gap",
"offset": 0,
"slot": "9",
"type": "t_array(t_uint256)50_storage",
"contract": "YTPoolManager",
"src": "contracts/ytLp/core/YTPoolManager.sol:345"
}
],
"types": {
"t_bool": {
"label": "bool",
"numberOfBytes": "1"
},
"t_struct(InitializableStorage)7_storage": {
"label": "struct Initializable.InitializableStorage",
"members": [
{
"label": "_initialized",
"type": "t_uint64",
"offset": 0,
"slot": "0"
},
{
"label": "_initializing",
"type": "t_bool",
"offset": 8,
"slot": "0"
}
],
"numberOfBytes": "32"
},
"t_struct(ReentrancyGuardStorage)222_storage": {
"label": "struct ReentrancyGuardUpgradeable.ReentrancyGuardStorage",
"members": [
{
"label": "_status",
"type": "t_uint256",
"offset": 0,
"slot": "0"
}
],
"numberOfBytes": "32"
},
"t_uint256": {
"label": "uint256",
"numberOfBytes": "32"
},
"t_uint64": {
"label": "uint64",
"numberOfBytes": "8"
},
"t_address": {
"label": "address",
"numberOfBytes": "20"
},
"t_array(t_uint256)50_storage": {
"label": "uint256[50]",
"numberOfBytes": "1600"
},
"t_mapping(t_address,t_bool)": {
"label": "mapping(address => bool)",
"numberOfBytes": "32"
},
"t_mapping(t_address,t_uint256)": {
"label": "mapping(address => uint256)",
"numberOfBytes": "32"
}
},
"namespaces": {
"erc7201:openzeppelin.storage.ReentrancyGuard": [
{
"contract": "ReentrancyGuardUpgradeable",
"label": "_status",
"type": "t_uint256",
"src": "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol:43",
"offset": 0,
"slot": "0"
}
],
"erc7201:openzeppelin.storage.Initializable": [
{
"contract": "Initializable",
"label": "_initialized",
"type": "t_uint64",
"src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:69",
"offset": 0,
"slot": "0"
},
{
"contract": "Initializable",
"label": "_initializing",
"type": "t_bool",
"src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:73",
"offset": 8,
"slot": "0"
}
]
}
}
}
}
}

View File

@@ -43,6 +43,35 @@
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "_token",
"type": "address"
},
{
"internalType": "uint256",
"name": "_amount",
"type": "uint256"
}
],
"name": "getAddLiquidityOutput",
"outputs": [
{
"internalType": "uint256",
"name": "usdyAmount",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "ytLPMintAmount",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
@@ -81,6 +110,35 @@
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "_tokenOut",
"type": "address"
},
{
"internalType": "uint256",
"name": "_ytLPAmount",
"type": "uint256"
}
],
"name": "getRemoveLiquidityOutput",
"outputs": [
{
"internalType": "uint256",
"name": "usdyAmount",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "amountOut",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{

View File

@@ -480,6 +480,35 @@
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "_token",
"type": "address"
},
{
"internalType": "uint256",
"name": "_amount",
"type": "uint256"
}
],
"name": "getAddLiquidityOutput",
"outputs": [
{
"internalType": "uint256",
"name": "usdyAmount",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "ytLPMintAmount",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
@@ -518,6 +547,35 @@
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "_tokenOut",
"type": "address"
},
{
"internalType": "uint256",
"name": "_ytLPAmount",
"type": "uint256"
}
],
"name": "getRemoveLiquidityOutput",
"outputs": [
{
"internalType": "uint256",
"name": "usdyAmount",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "amountOut",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "gov",

File diff suppressed because one or more lines are too long

View File

@@ -21,6 +21,7 @@ interface IYTPoolManager {
function getPrice(bool _maximise) external view returns (uint256);
function getAumInUsdy(bool _maximise) external view returns (uint256);
function getAddLiquidityOutput(address _token, uint256 _amount) external view returns (uint256 usdyAmount, uint256 ytLPMintAmount);
function getRemoveLiquidityOutput(address _tokenOut, uint256 _ytLPAmount) external view returns (uint256 usdyAmount, uint256 amountOut);
function onLPTransfer(address _from, address _to) external;
}

View File

@@ -286,10 +286,60 @@ contract YTPoolManager is Initializable, UUPSUpgradeable, ReentrancyGuardUpgrade
return aum;
}
/**
* @notice 预估添加流动性能获得的 ytLP 数量
* @param _token 存入的 token 地址
* @param _amount 存入的 token 数量
* @return usdyAmount 扣除手续费后实际得到的 USDY 数量
* @return ytLPMintAmount 预计铸造的 ytLP 数量
*/
function getAddLiquidityOutput(
address _token,
uint256 _amount
) external view returns (uint256 usdyAmount, uint256 ytLPMintAmount) {
// 模拟 buyUSDYtoken → USDY含动态手续费
uint256 price = IYTVault(ytVault).getMinPrice(_token);
uint256 rawUsdyAmount = _amount * price / PRICE_PRECISION;
uint256 feeBasisPoints = IYTVault(ytVault).getSwapFeeBasisPoints(_token, usdy, rawUsdyAmount);
uint256 amountAfterFees = _amount - (_amount * feeBasisPoints / BASIS_POINTS_DIVISOR);
usdyAmount = amountAfterFees * price / PRICE_PRECISION;
// 模拟 _addLiquidityUSDY → ytLP mint 数量
uint256 aumInUsdy = getAumInUsdy(true);
uint256 ytLPSupply = IERC20(ytLP).totalSupply();
if (ytLPSupply == 0) {
ytLPMintAmount = usdyAmount;
} else {
ytLPMintAmount = usdyAmount * ytLPSupply / aumInUsdy;
}
}
/**
* @notice 预估移除流动性能获得的 token 数量
* @param _tokenOut 取出的 token 地址
* @param _ytLPAmount 销毁的 ytLP 数量
* @return usdyAmount ytLP 对应的 USDY 价值
* @return amountOut 扣除手续费后实际获得的 token 数量
*/
function getRemoveLiquidityOutput(
address _tokenOut,
uint256 _ytLPAmount
) external view returns (uint256 usdyAmount, uint256 amountOut) {
// 模拟 _removeLiquidityytLP → USDY
uint256 aumInUsdy = getAumInUsdy(false);
uint256 ytLPSupply = IERC20(ytLP).totalSupply();
usdyAmount = _ytLPAmount * aumInUsdy / ytLPSupply;
// 模拟 sellUSDYUSDY → token含动态手续费
uint256 price = IYTVault(ytVault).getMaxPrice(_tokenOut);
uint256 redemptionAmount = usdyAmount * PRICE_PRECISION / price;
uint256 feeBasisPoints = IYTVault(ytVault).getRedemptionFeeBasisPoints(_tokenOut, redemptionAmount);
amountOut = redemptionAmount * (BASIS_POINTS_DIVISOR - feeBasisPoints) / BASIS_POINTS_DIVISOR;
}
/**
* @dev 预留存储空间,用于未来升级时添加新的状态变量
* 50个slot = 50 * 32 bytes = 1600 bytes
*/
uint256[50] private __gap;
}

View File

@@ -22,11 +22,21 @@
},
"YTPoolManager": {
"proxy": "0xb11824eAA659F8A4648711709dA60720d5Cdabd2",
"implementation": "0x144cC96e9b1DC5EC118DF49167DA83048A3050ae"
"implementation": "0xf4cE104E687F5d2064481cbD5B24ED52d7C324b0"
},
"YTRewardRouter": {
"proxy": "0x5af5A51F7702024E7387bba7497DC9965C00F16E",
"implementation": "0x3688CDd7A25613E7b1E7E0ee1aA46c21F66D27F3"
}
}
},
"upgradeHistory": [
{
"timestamp": "2026-03-09T02:23:16.418Z",
"contract": "YTPoolManager",
"oldImplementation": "0x144cC96e9b1DC5EC118DF49167DA83048A3050ae",
"newImplementation": "0xf4cE104E687F5d2064481cbD5B24ED52d7C324b0",
"upgrader": "0xa013422A5918CD099C63c8CC35283EACa99a705d"
}
],
"lastUpdate": "2026-03-09T02:23:16.418Z"
}

View File

@@ -1 +1 @@
{"id":"d81065d09c259d5f","source_id_to_path":{"0":"lib/forge-std/src/Base.sol","1":"lib/forge-std/src/Script.sol","2":"lib/forge-std/src/StdChains.sol","3":"lib/forge-std/src/StdCheats.sol","4":"lib/forge-std/src/StdConstants.sol","5":"lib/forge-std/src/StdJson.sol","6":"lib/forge-std/src/StdMath.sol","7":"lib/forge-std/src/StdStorage.sol","8":"lib/forge-std/src/StdStyle.sol","9":"lib/forge-std/src/StdUtils.sol","10":"lib/forge-std/src/Vm.sol","11":"lib/forge-std/src/console.sol","12":"lib/forge-std/src/console2.sol","13":"lib/forge-std/src/interfaces/IMulticall3.sol","14":"lib/forge-std/src/safeconsole.sol","15":"scripts/test.s.sol"},"language":"Solidity"}
{"id":"eabedd7944f1777c","source_id_to_path":{"0":"lib/forge-std/src/Base.sol","1":"lib/forge-std/src/Script.sol","2":"lib/forge-std/src/StdChains.sol","3":"lib/forge-std/src/StdCheats.sol","4":"lib/forge-std/src/StdConstants.sol","5":"lib/forge-std/src/StdJson.sol","6":"lib/forge-std/src/StdMath.sol","7":"lib/forge-std/src/StdStorage.sol","8":"lib/forge-std/src/StdStyle.sol","9":"lib/forge-std/src/StdUtils.sol","10":"lib/forge-std/src/Vm.sol","11":"lib/forge-std/src/console.sol","12":"lib/forge-std/src/console2.sol","13":"lib/forge-std/src/interfaces/IMulticall3.sol","14":"lib/forge-std/src/safeconsole.sol","15":"scripts/test.s.sol"},"language":"Solidity"}

File diff suppressed because one or more lines are too long

View File

@@ -12,7 +12,7 @@ contract TestFun is Script {
function run() external {
address from = 0xa013422A5918CD099C63c8CC35283EACa99a705d;
address to = 0x7f9eEA491eE53045594ee4669327f0355aCd0e58;
address to = 0x20B94C5E5b7361552E0548161a58696aA6FeDBd4;
bytes memory data = hex"7229bc3c0000000000000000000000000000000000000000000000000de0b6b3a7640000";

View File

@@ -59,7 +59,7 @@ async function main() {
console.log("🔄 Phase 2: 验证升级结果");
console.log(" YTPoolManager Proxy (不变):", upgradedYTPoolManagerAddress);
console.log(" Owner:", await upgradedYTPoolManager.owner());
console.log(" Gov:", await upgradedYTPoolManager.gov());
console.log("");
// ========== 保存更新的部署信息 ==========