diff --git a/contracts/0.8.25/vaults/Dashboard.sol b/contracts/0.8.25/vaults/Dashboard.sol index ea4c3934d..6673f3203 100644 --- a/contracts/0.8.25/vaults/Dashboard.sol +++ b/contracts/0.8.25/vaults/Dashboard.sol @@ -135,18 +135,18 @@ contract Dashboard is Permissions { /** * @notice Returns the reserve ratio of the vault in basis points - * @return The reserve ratio as a uint16 + * @return The reserve ratio in basis points as a uint16 */ function reserveRatioBP() public view returns (uint16) { return vaultSocket().reserveRatioBP; } /** - * @notice Returns the threshold reserve ratio of the vault in basis points. - * @return The threshold reserve ratio as a uint16. + * @notice Returns the rebalance threshold of the vault in basis points. + * @return The rebalance threshold in basis points as a uint16. */ - function thresholdReserveRatioBP() external view returns (uint16) { - return vaultSocket().reserveRatioThresholdBP; + function rebalanceThresholdBP() external view returns (uint16) { + return vaultSocket().rebalanceThresholdBP; } /** diff --git a/contracts/0.8.25/vaults/VaultHub.sol b/contracts/0.8.25/vaults/VaultHub.sol index f9c517c2b..fd2df762e 100644 --- a/contracts/0.8.25/vaults/VaultHub.sol +++ b/contracts/0.8.25/vaults/VaultHub.sol @@ -42,8 +42,8 @@ abstract contract VaultHub is PausableUntilWithRoles { uint96 shareLimit; /// @notice minimal share of ether that is reserved for each stETH minted uint16 reserveRatioBP; - /// @notice if vault's reserve decreases to this threshold ratio, it should be force rebalanced - uint16 reserveRatioThresholdBP; + /// @notice if vault's reserve decreases to this threshold, it should be force rebalanced + uint16 rebalanceThresholdBP; /// @notice treasury fee in basis points uint16 treasuryFeeBP; /// @notice if true, vault is disconnected and fee is not accrued @@ -135,8 +135,8 @@ abstract contract VaultHub is PausableUntilWithRoles { return $.sockets[$.vaultIndex[_vault]]; } - /// @notice checks if the vault is healthy by comparing its valuation against minted shares - /// @dev A vault is considered healthy when its valuation is sufficient to cover the current value of minted shares + /// @notice checks if the vault is healthy by comparing its projected valuation after applying rebalance threshold + /// against the current value of minted shares /// @param _vault vault address /// @return true if vault is healthy, false otherwise function isVaultHealthy(address _vault) public view returns (bool) { @@ -144,29 +144,29 @@ abstract contract VaultHub is PausableUntilWithRoles { if (socket.sharesMinted == 0) return true; return ( - IStakingVault(_vault).valuation() * (TOTAL_BASIS_POINTS - socket.reserveRatioThresholdBP) / TOTAL_BASIS_POINTS + IStakingVault(_vault).valuation() * (TOTAL_BASIS_POINTS - socket.rebalanceThresholdBP) / TOTAL_BASIS_POINTS ) >= STETH.getPooledEthBySharesRoundUp(socket.sharesMinted); } /// @notice connects a vault to the hub /// @param _vault vault address /// @param _shareLimit maximum number of stETH shares that can be minted by the vault - /// @param _reserveRatioBP minimum Reserve ratio in basis points - /// @param _reserveRatioThresholdBP reserve ratio that makes possible to force rebalance on the vault (in basis points) + /// @param _reserveRatioBP minimum reserve ratio in basis points + /// @param _rebalanceThresholdBP threshold to force rebalance on the vault in basis points /// @param _treasuryFeeBP treasury fee in basis points /// @dev msg.sender must have VAULT_MASTER_ROLE function connectVault( address _vault, uint256 _shareLimit, uint256 _reserveRatioBP, - uint256 _reserveRatioThresholdBP, + uint256 _rebalanceThresholdBP, uint256 _treasuryFeeBP ) external onlyRole(VAULT_MASTER_ROLE) { if (_vault == address(0)) revert ZeroArgument("_vault"); if (_reserveRatioBP == 0) revert ZeroArgument("_reserveRatioBP"); if (_reserveRatioBP > TOTAL_BASIS_POINTS) revert ReserveRatioTooHigh(_vault, _reserveRatioBP, TOTAL_BASIS_POINTS); - if (_reserveRatioThresholdBP == 0) revert ZeroArgument("_reserveRatioThresholdBP"); - if (_reserveRatioThresholdBP > _reserveRatioBP) revert ReserveRatioThresholdTooHigh(_vault, _reserveRatioThresholdBP, _reserveRatioBP); + if (_rebalanceThresholdBP == 0) revert ZeroArgument("_rebalanceThresholdBP"); + if (_rebalanceThresholdBP > _reserveRatioBP) revert RebalanceThresholdTooHigh(_vault, _rebalanceThresholdBP, _reserveRatioBP); if (_treasuryFeeBP > TOTAL_BASIS_POINTS) revert TreasuryFeeTooHigh(_vault, _treasuryFeeBP, TOTAL_BASIS_POINTS); if (vaultsCount() == CONNECTED_VAULTS_LIMIT) revert TooManyVaults(); _checkShareLimitUpperBound(_vault, _shareLimit); @@ -182,7 +182,7 @@ abstract contract VaultHub is PausableUntilWithRoles { 0, // sharesMinted uint96(_shareLimit), uint16(_reserveRatioBP), - uint16(_reserveRatioThresholdBP), + uint16(_rebalanceThresholdBP), uint16(_treasuryFeeBP), false // pendingDisconnect ); @@ -191,7 +191,7 @@ abstract contract VaultHub is PausableUntilWithRoles { IStakingVault(_vault).lock(CONNECT_DEPOSIT); - emit VaultConnected(_vault, _shareLimit, _reserveRatioBP, _reserveRatioThresholdBP, _treasuryFeeBP); + emit VaultConnected(_vault, _shareLimit, _reserveRatioBP, _rebalanceThresholdBP, _treasuryFeeBP); } /// @notice updates share limit for the vault @@ -542,7 +542,7 @@ abstract contract VaultHub is PausableUntilWithRoles { if (isVaultHealthy(_vault)) revert AlreadyHealthy(_vault); } - event VaultConnected(address indexed vault, uint256 capShares, uint256 minReserveRatio, uint256 reserveRatioThreshold, uint256 treasuryFeeBP); + event VaultConnected(address indexed vault, uint256 capShares, uint256 minReserveRatio, uint256 rebalanceThreshold, uint256 treasuryFeeBP); event ShareLimitUpdated(address indexed vault, uint256 newShareLimit); event VaultDisconnected(address indexed vault); event MintedSharesOnVault(address indexed vault, uint256 amountOfShares); @@ -564,7 +564,7 @@ abstract contract VaultHub is PausableUntilWithRoles { error TooManyVaults(); error ShareLimitTooHigh(address vault, uint256 capShares, uint256 maxCapShares); error ReserveRatioTooHigh(address vault, uint256 reserveRatioBP, uint256 maxReserveRatioBP); - error ReserveRatioThresholdTooHigh(address vault, uint256 reserveRatioThresholdBP, uint256 maxReserveRatioBP); + error RebalanceThresholdTooHigh(address vault, uint256 rebalanceThresholdBP, uint256 maxRebalanceThresholdBP); error TreasuryFeeTooHigh(address vault, uint256 treasuryFeeBP, uint256 maxTreasuryFeeBP); error ExternalSharesCapReached(address vault, uint256 capShares, uint256 maxMintableExternalShares); error InsufficientValuationToMint(address vault, uint256 valuation); diff --git a/test/0.8.25/vaults/dashboard/dashboard.test.ts b/test/0.8.25/vaults/dashboard/dashboard.test.ts index 6bf64cf27..e0fafd653 100644 --- a/test/0.8.25/vaults/dashboard/dashboard.test.ts +++ b/test/0.8.25/vaults/dashboard/dashboard.test.ts @@ -182,7 +182,7 @@ describe("Dashboard.sol", () => { sharesMinted: 555n, shareLimit: 1000n, reserveRatioBP: 1000n, - reserveRatioThresholdBP: 800n, + rebalanceThresholdBP: 800n, treasuryFeeBP: 500n, pendingDisconnect: false, }; @@ -193,7 +193,7 @@ describe("Dashboard.sol", () => { expect(await dashboard.shareLimit()).to.equal(sockets.shareLimit); expect(await dashboard.sharesMinted()).to.equal(sockets.sharesMinted); expect(await dashboard.reserveRatioBP()).to.equal(sockets.reserveRatioBP); - expect(await dashboard.thresholdReserveRatioBP()).to.equal(sockets.reserveRatioThresholdBP); + expect(await dashboard.rebalanceThresholdBP()).to.equal(sockets.rebalanceThresholdBP); expect(await dashboard.treasuryFeeBP()).to.equal(sockets.treasuryFeeBP); }); }); @@ -218,7 +218,7 @@ describe("Dashboard.sol", () => { shareLimit: 1000000000n, sharesMinted: 555n, reserveRatioBP: 1000n, - reserveRatioThresholdBP: 800n, + rebalanceThresholdBP: 800n, treasuryFeeBP: 500n, pendingDisconnect: false, }; @@ -240,7 +240,7 @@ describe("Dashboard.sol", () => { shareLimit: 100n, sharesMinted: 0n, reserveRatioBP: 1000n, - reserveRatioThresholdBP: 800n, + rebalanceThresholdBP: 800n, treasuryFeeBP: 500n, pendingDisconnect: false, }; @@ -260,7 +260,7 @@ describe("Dashboard.sol", () => { shareLimit: 1000000000n, sharesMinted: 555n, reserveRatioBP: 10_000n, - reserveRatioThresholdBP: 800n, + rebalanceThresholdBP: 800n, treasuryFeeBP: 500n, pendingDisconnect: false, }; @@ -280,7 +280,7 @@ describe("Dashboard.sol", () => { shareLimit: 10000000n, sharesMinted: 555n, reserveRatioBP: 0n, - reserveRatioThresholdBP: 0n, + rebalanceThresholdBP: 0n, treasuryFeeBP: 500n, pendingDisconnect: false, }; @@ -308,7 +308,7 @@ describe("Dashboard.sol", () => { shareLimit: 10000000n, sharesMinted: 0n, reserveRatioBP: 1000n, - reserveRatioThresholdBP: 800n, + rebalanceThresholdBP: 800n, treasuryFeeBP: 500n, pendingDisconnect: false, }; @@ -334,7 +334,7 @@ describe("Dashboard.sol", () => { shareLimit: 10000000n, sharesMinted: 900n, reserveRatioBP: 1000n, - reserveRatioThresholdBP: 800n, + rebalanceThresholdBP: 800n, treasuryFeeBP: 500n, pendingDisconnect: false, }; @@ -357,7 +357,7 @@ describe("Dashboard.sol", () => { shareLimit: 10000000n, sharesMinted: 10000n, reserveRatioBP: 1000n, - reserveRatioThresholdBP: 800n, + rebalanceThresholdBP: 800n, treasuryFeeBP: 500n, pendingDisconnect: false, }; @@ -378,7 +378,7 @@ describe("Dashboard.sol", () => { shareLimit: 10000000n, sharesMinted: 500n, reserveRatioBP: 1000n, - reserveRatioThresholdBP: 800n, + rebalanceThresholdBP: 800n, treasuryFeeBP: 500n, pendingDisconnect: false, }; @@ -402,7 +402,7 @@ describe("Dashboard.sol", () => { shareLimit: 500n, sharesMinted: 500n, reserveRatioBP: 1000n, - reserveRatioThresholdBP: 800n, + rebalanceThresholdBP: 800n, treasuryFeeBP: 500n, pendingDisconnect: false, }; diff --git a/test/0.8.25/vaults/vaultFactory.test.ts b/test/0.8.25/vaults/vaultFactory.test.ts index c2941069d..800817bc8 100644 --- a/test/0.8.25/vaults/vaultFactory.test.ts +++ b/test/0.8.25/vaults/vaultFactory.test.ts @@ -208,13 +208,13 @@ describe("VaultFactory.sol", () => { const config1 = { shareLimit: 10n, minReserveRatioBP: 500n, - thresholdReserveRatioBP: 20n, + rebalanceThresholdBP: 20n, treasuryFeeBP: 500n, }; const config2 = { shareLimit: 20n, minReserveRatioBP: 200n, - thresholdReserveRatioBP: 20n, + rebalanceThresholdBP: 20n, treasuryFeeBP: 600n, }; @@ -242,7 +242,7 @@ describe("VaultFactory.sol", () => { await vault1.getAddress(), config1.shareLimit, config1.minReserveRatioBP, - config1.thresholdReserveRatioBP, + config1.rebalanceThresholdBP, config1.treasuryFeeBP, ), ).to.revertedWithCustomError(accounting, "VaultProxyNotAllowed"); @@ -259,7 +259,7 @@ describe("VaultFactory.sol", () => { await vault1.getAddress(), config1.shareLimit, config1.minReserveRatioBP, - config1.thresholdReserveRatioBP, + config1.rebalanceThresholdBP, config1.treasuryFeeBP, ); @@ -289,7 +289,7 @@ describe("VaultFactory.sol", () => { await vault2.getAddress(), config2.shareLimit, config2.minReserveRatioBP, - config2.thresholdReserveRatioBP, + config2.rebalanceThresholdBP, config2.treasuryFeeBP, ), ).to.not.revertedWithCustomError(accounting, "VaultProxyNotAllowed"); diff --git a/test/0.8.25/vaults/vaulthub/vaulthub.hub.test.ts b/test/0.8.25/vaults/vaulthub/vaulthub.hub.test.ts index f995ab26a..a4a49e2f8 100644 --- a/test/0.8.25/vaults/vaulthub/vaulthub.hub.test.ts +++ b/test/0.8.25/vaults/vaulthub/vaulthub.hub.test.ts @@ -65,7 +65,7 @@ describe("VaultHub.sol:hub", () => { options?: { shareLimit?: bigint; reserveRatioBP?: bigint; - reserveRatioThresholdBP?: bigint; + rebalanceThresholdBP?: bigint; treasuryFeeBP?: bigint; }, ) { @@ -77,7 +77,7 @@ describe("VaultHub.sol:hub", () => { await vault.getAddress(), options?.shareLimit ?? SHARE_LIMIT, options?.reserveRatioBP ?? RESERVE_RATIO_BP, - options?.reserveRatioThresholdBP ?? RESERVE_RATIO_THRESHOLD_BP, + options?.rebalanceThresholdBP ?? RESERVE_RATIO_THRESHOLD_BP, options?.treasuryFeeBP ?? TREASURY_FEE_BP, ); @@ -216,7 +216,7 @@ describe("VaultHub.sol:hub", () => { expect(lastVaultSocket.sharesMinted).to.equal(0n); expect(lastVaultSocket.shareLimit).to.equal(SHARE_LIMIT); expect(lastVaultSocket.reserveRatioBP).to.equal(RESERVE_RATIO_BP); - expect(lastVaultSocket.reserveRatioThresholdBP).to.equal(RESERVE_RATIO_THRESHOLD_BP); + expect(lastVaultSocket.rebalanceThresholdBP).to.equal(RESERVE_RATIO_THRESHOLD_BP); expect(lastVaultSocket.treasuryFeeBP).to.equal(TREASURY_FEE_BP); expect(lastVaultSocket.pendingDisconnect).to.equal(false); }); @@ -231,7 +231,7 @@ describe("VaultHub.sol:hub", () => { expect(vaultSocket.sharesMinted).to.equal(0n); expect(vaultSocket.shareLimit).to.equal(0n); expect(vaultSocket.reserveRatioBP).to.equal(0n); - expect(vaultSocket.reserveRatioThresholdBP).to.equal(0n); + expect(vaultSocket.rebalanceThresholdBP).to.equal(0n); expect(vaultSocket.treasuryFeeBP).to.equal(0n); expect(vaultSocket.pendingDisconnect).to.equal(false); }); @@ -245,7 +245,7 @@ describe("VaultHub.sol:hub", () => { expect(vaultSocket.sharesMinted).to.equal(0n); expect(vaultSocket.shareLimit).to.equal(SHARE_LIMIT); expect(vaultSocket.reserveRatioBP).to.equal(RESERVE_RATIO_BP); - expect(vaultSocket.reserveRatioThresholdBP).to.equal(RESERVE_RATIO_THRESHOLD_BP); + expect(vaultSocket.rebalanceThresholdBP).to.equal(RESERVE_RATIO_THRESHOLD_BP); expect(vaultSocket.treasuryFeeBP).to.equal(TREASURY_FEE_BP); expect(vaultSocket.pendingDisconnect).to.equal(false); }); @@ -274,8 +274,8 @@ describe("VaultHub.sol:hub", () => { for (let i = 0; i < 50; i++) { const snapshot = await Snapshot.take(); - const reserveRatioThresholdBP = tbi(10000); - const reserveRatioBP = BigIntMath.min(reserveRatioThresholdBP + tbi(1000), TOTAL_BASIS_POINTS); + const rebalanceThresholdBP = tbi(10000); + const reserveRatioBP = BigIntMath.min(rebalanceThresholdBP + tbi(1000), TOTAL_BASIS_POINTS); const valuationEth = tbi(100); const valuation = ether(valuationEth.toString()); @@ -284,13 +284,13 @@ describe("VaultHub.sol:hub", () => { const isSlashing = Math.random() < 0.5; const slashed = isSlashing ? ether(tbi(valuationEth).toString()) : 0n; - const treashold = ((valuation - slashed) * (TOTAL_BASIS_POINTS - reserveRatioThresholdBP)) / TOTAL_BASIS_POINTS; + const treashold = ((valuation - slashed) * (TOTAL_BASIS_POINTS - rebalanceThresholdBP)) / TOTAL_BASIS_POINTS; const expectedHealthy = treashold >= mintable; const vault = await createAndConnectVault(vaultFactory, { shareLimit: ether("100"), // just to bypass the share limit check reserveRatioBP: reserveRatioBP, - reserveRatioThresholdBP: reserveRatioThresholdBP, + rebalanceThresholdBP: rebalanceThresholdBP, }); const vaultAddress = await vault.getAddress(); @@ -309,7 +309,7 @@ describe("VaultHub.sol:hub", () => { expect(actualHealthy).to.equal(expectedHealthy); } catch (error) { console.log(`Test failed with parameters: - Reserve Ratio Threshold: ${reserveRatioThresholdBP} + Rebalance Threshold: ${rebalanceThresholdBP} Reserve Ratio: ${reserveRatioBP} Valuation: ${valuation} ETH Minted: ${mintable} stETH @@ -328,7 +328,7 @@ describe("VaultHub.sol:hub", () => { const vault = await createAndConnectVault(vaultFactory, { shareLimit: ether("100"), // just to bypass the share limit check reserveRatioBP: 50_00n, // 50% - reserveRatioThresholdBP: 50_00n, // 50% + rebalanceThresholdBP: 50_00n, // 50% }); const vaultAddress = await vault.getAddress(); @@ -353,7 +353,7 @@ describe("VaultHub.sol:hub", () => { const vault = await createAndConnectVault(vaultFactory, { shareLimit: ether("100"), // just to bypass the share limit check reserveRatioBP: 50_00n, // 50% - reserveRatioThresholdBP: 50_00n, // 50% + rebalanceThresholdBP: 50_00n, // 50% }); const vaultAddress = await vault.getAddress(); @@ -392,7 +392,7 @@ describe("VaultHub.sol:hub", () => { const vault = await createAndConnectVault(vaultFactory, { shareLimit: ether("100"), // just to bypass the share limit check reserveRatioBP: 1n, // 0.01% - reserveRatioThresholdBP: 1n, // 0.01% + rebalanceThresholdBP: 1n, // 0.01% }); const vaultAddress = await vault.getAddress(); @@ -429,7 +429,7 @@ describe("VaultHub.sol:hub", () => { const vault = await createAndConnectVault(vaultFactory, { shareLimit: ether("100"), reserveRatioBP: 50_00n, // 50% - reserveRatioThresholdBP: 50_00n, // 50% + rebalanceThresholdBP: 50_00n, // 50% }); const vaultAddress = await vault.getAddress(); @@ -484,7 +484,7 @@ describe("VaultHub.sol:hub", () => { ).to.be.revertedWithCustomError(vaultHub, "ZeroArgument"); }); - it("reverts if reserve ration is too high", async () => { + it("reverts if reserve ratio is too high", async () => { const tooHighReserveRatioBP = TOTAL_BASIS_POINTS + 1n; await expect( vaultHub @@ -495,19 +495,19 @@ describe("VaultHub.sol:hub", () => { .withArgs(vaultAddress, tooHighReserveRatioBP, TOTAL_BASIS_POINTS); }); - it("reverts if reserve ratio threshold BP is zero", async () => { + it("reverts if rebalance threshold BP is zero", async () => { await expect( vaultHub.connect(user).connectVault(vaultAddress, SHARE_LIMIT, RESERVE_RATIO_BP, 0n, TREASURY_FEE_BP), ).to.be.revertedWithCustomError(vaultHub, "ZeroArgument"); }); - it("reverts if reserve ratio threshold BP is higher than reserve ratio BP", async () => { + it("reverts if rebalance threshold BP is higher than reserve ratio BP", async () => { await expect( vaultHub .connect(user) .connectVault(vaultAddress, SHARE_LIMIT, RESERVE_RATIO_BP, RESERVE_RATIO_BP + 1n, TREASURY_FEE_BP), ) - .to.be.revertedWithCustomError(vaultHub, "ReserveRatioThresholdTooHigh") + .to.be.revertedWithCustomError(vaultHub, "RebalanceThresholdTooHigh") .withArgs(vaultAddress, RESERVE_RATIO_BP + 1n, RESERVE_RATIO_BP); }); diff --git a/test/integration/vaults-happy-path.integration.ts b/test/integration/vaults-happy-path.integration.ts index e5c872014..34d5bb8b9 100644 --- a/test/integration/vaults-happy-path.integration.ts +++ b/test/integration/vaults-happy-path.integration.ts @@ -49,7 +49,7 @@ describe("Scenario: Staking Vaults Happy Path", () => { let depositContract: string; const reserveRatio = 10_00n; // 10% of ETH allocation as reserve - const reserveRatioThreshold = 8_00n; // 8% of reserve ratio + const rebalanceThreshold = 8_00n; // 8% is a threshold to force rebalance on the vault const mintableRatio = TOTAL_BASIS_POINTS - reserveRatio; // 90% LTV let delegation: Delegation; @@ -220,7 +220,7 @@ describe("Scenario: Staking Vaults Happy Path", () => { await accounting .connect(agentSigner) - .connectVault(stakingVault, shareLimit, reserveRatio, reserveRatioThreshold, treasuryFeeBP); + .connectVault(stakingVault, shareLimit, reserveRatio, rebalanceThreshold, treasuryFeeBP); expect(await accounting.vaultsCount()).to.equal(1n); expect(await stakingVault.locked()).to.equal(VAULT_CONNECTION_DEPOSIT);