Stability Pool Manager Contract
The Stability Pool Manager contract coordinates rebalancing and harvesting operations between the two stability pools for a market.
Overview
The Stability Pool Manager (StabilityPoolManager_v1) is a UUPS upgradeable contract that manages two fixed stability pools and coordinates system rebalancing and yield harvesting. It does not create pools dynamically; instead, it manages two pre-configured pools set during contract construction.
Contract Architecture
- Upgradeable: Uses UUPS (Universal Upgradeable Proxy Standard) pattern
- Storage: Uses ERC-7201 namespaced storage
- Access Control: Uses BaoOwnableRoles for role-based access control
- Reentrancy Protection: Uses OpenZeppelin's ReentrancyGuardTransientUpgradeable
Immutable Addresses
Set during contract construction (cannot be changed):
- MINTER: Address of the Minter contract
- PEGGED_TOKEN: The pegged token contract (haToken)
- WRAPPED_COLLATERAL_TOKEN: The wrapped collateral token (e.g., wstETH)
- LEVERAGED_TOKEN: The leveraged token contract (hsToken)
- TREASURY: Protocol treasury address
- _STABILITY_POOL_COLLATERAL: Address of the collateral stability pool
- _STABILITY_POOL_LEVERAGED: Address of the leveraged (Sail) stability pool
Storage State
- rebalanceBountyRatio: Fixed bounty amount for rebalancing (as ratio of liquidation proceeds)
- rebalanceThreshold: The collateral ratio threshold at which rebalancing should occur
- harvestBountyRatio: Percentage-based bounty for harvesting (as ratio of harvested amount)
- harvestCutRatio: Percentage-based cut for harvesting (as ratio of harvested amount)
- feeReceiver: Address that receives the harvest cut (defaults to TREASURY if not set)
Key Functions
Core Operations
rebalance(address bountyReceiver, uint256 minPeggedLiquidated)
Rebalances the system when the collateral ratio falls below the rebalance threshold by liquidating pegged tokens from stability pools.
Parameters:
bountyReceiver: Address to receive the rebalance bountyminPeggedLiquidated: Minimum amount of pegged tokens expected to be liquidated (slippage protection)
Returns:
peggedLiquidated: Total amount of pegged tokens liquidated
Process:
- Checks if collateral ratio is below rebalance threshold
- Calculates how much pegged tokens need to be liquidated to reach the threshold
- Distributes liquidation between pools based on their weighted holdings
- Sweeps pegged tokens from both pools
- Redeems pegged tokens via Minter (fee-free)
- Distributes liquidation proceeds:
- Takes rebalance bounty for caller
- Transfers remainder to respective stability pools
- Notifies pools of liquidation via
notifyLiquidation()
Effects:
- Reduces pegged token supply
- Increases collateral ratio back above threshold
- Distributes wrapped collateral to collateral pool
- Distributes leveraged tokens to leveraged pool
harvest(address bountyReceiver, uint256 minBounty)
Harvests yield accrued from holding wrapped collateral (e.g., staking rewards) and distributes it to stability pools.
Parameters:
bountyReceiver: Address to receive the harvest bountyminBounty: Minimum bounty amount expected (slippage protection)
Returns:
harvestedAmount: Total amount harvested
Process:
- Checks if there's harvestable amount available from Minter
- Calculates bounty and cut amounts
- Sweeps harvestable wrapped collateral from Minter
- Distributes:
- Bounty to caller
- Cut to fee receiver (or treasury if not set)
- Remainder proportionally to stability pools based on their pegged token holdings
Effects:
- Transfers yield to stability pools as rewards
- Rewards are distributed via
depositReward()on each pool - Pools distribute rewards to depositors via their gauge systems
View Functions
Pool Information
stabilityPools() returns (address[] memory)- Returns array of both stability pool addresseshasStabilityPool(address stabilityPool) returns (bool)- Checks if an address is one of the managed pools
State Queries
harvestable() returns (uint256)- Amount available to harvest from Minterrebalanceable() returns (bool)- Whether system can be rebalanced (CR below threshold)rebalanceThreshold() returns (uint256)- Current rebalance threshold collateral ratiorebalanceBountyRatio() returns (uint256)- Current rebalance bounty ratioharvestBountyRatio() returns (uint256)- Current harvest bounty ratioharvestCutRatio() returns (uint256)- Current harvest cut ratiofeeReceiver() returns (address)- Address receiving harvest cuts
Admin Functions (Owner Only)
Configuration Updates
updateRebalanceThreshold(uint256 newRatio)- Updates the collateral ratio threshold for rebalancing- Must be greater than 1 ether
updateRebalanceBountyRatio(uint256 rebalanceRatio_)- Updates rebalance bounty ratio- Must be less than or equal to 1 ether
updateHarvestBountyRatio(uint256 harvestRatio_)- Updates harvest bounty ratio- Must be less than or equal to 1 ether
updateHarvestCutRatio(uint256 harvestCutRatio_)- Updates harvest cut ratio- Must be less than or equal to 1 ether
updateFeeReceiver(address feeReceiver_)- Updates the fee receiver address
Rebalancing Mechanism
Rebalancing occurs when the collateral ratio falls below the configured threshold:
- Trigger: Collateral ratio below rebalance threshold
- Calculation: Determines how much pegged tokens to liquidate to reach threshold
- Distribution: Splits liquidation between pools based on:
- Pool holdings (pegged token balances)
- Effectiveness (collateral pool vs leveraged pool)
- Execution: Uses Minter's fee-free redemption to liquidate
- Rewards: Distributes liquidation proceeds to pools, minus bounty
The rebalance bounty incentivizes keepers to call this function when needed.
Harvesting Mechanism
Harvesting extracts yield accrued from wrapped collateral:
- Source: Yield from holding wrapped collateral (e.g., stETH rewards)
- Calculation: Determines harvestable amount from Minter
- Distribution:
- Bounty to caller (incentive)
- Cut to fee receiver (protocol revenue)
- Remainder to pools (proportional to holdings)
- Rewards: Pools distribute harvested yield to depositors
The harvest bounty incentivizes keepers to call this function regularly.
Dependencies
- MINTER: Reference to the Minter contract (for rebalancing and harvesting)
- LEVERAGED_TOKEN: The leveraged token contract (hsToken)
- PEGGED_TOKEN: The pegged token contract (haToken)
- WRAPPED_COLLATERAL_TOKEN: The wrapped collateral token (e.g., wstETH)
- TREASURY: Protocol treasury address (fallback for harvest cuts)
- feeReceiver: Address that receives protocol fees (harvest cuts)
- _STABILITY_POOL_COLLATERAL: Collateral stability pool contract
- _STABILITY_POOL_LEVERAGED: Leveraged (Sail) stability pool contract
Stability Pool Types
The contract manages two fixed pools:
-
Collateral Stability Pool (
_STABILITY_POOL_COLLATERAL):- Uses wrapped collateral (e.g., wstETH) as liquidation token
- Receives wrapped collateral during rebalancing
- Provides stability through collateral-backed liquidations
-
Sail Stability Pool (
_STABILITY_POOL_LEVERAGED):- Uses leveraged tokens (hsTokens) as liquidation token
- Receives leveraged tokens during rebalancing
- Provides stability through leveraged token liquidations
Security Considerations
- All mutating functions are protected by
nonReentrantmodifier - Rebalancing can only occur when collateral ratio is below threshold
- Harvesting requires non-zero harvestable amount
- Bounty and cut ratios are capped at 1 ether (100%)
- Rebalance threshold must be > 1 ether to prevent invalid configurations
- Uses safe token transfers throughout