Minter Contract
The Minter contract is responsible for minting and redeeming leveraged tokens (hsTokens) and pegged tokens (haTokens) in exchange for wrapped collateral.
Overview
The Minter contract (Minter_v1) is a UUPS upgradeable contract that handles the core minting and redemption operations for Harbor Protocol markets. It implements a sophisticated fee/discount system based on collateral ratios and provides price stability through stability pools.
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):
- WRAPPED_COLLATERAL_TOKEN: The wrapped collateral token (e.g., wstETH)
- PEGGED_TOKEN: The pegged token contract (haToken, e.g., haETH)
- LEVERAGED_TOKEN: The leveraged token contract (hsToken, e.g., hsETHxFxSAVE)
- _BURN_SIGNATURE: The burn signature type for the pegged token (Burn1Arg, Burn2Arg, or BurnFrom)
Storage State
- peggedTokenBalance: Total pegged tokens minted by this contract (tracks only tokens minted here, not total supply)
- underlyingCollateral: Total underlying collateral backing the tokens
- reservePool: Address of the reserve pool (source of discounts)
- feeReceiver: Address that receives protocol fees
- priceOracle: Address of the price oracle contract
- incentiveConfig: Configuration for fees, discounts, and disallows based on collateral ratio bands
Key Functions
Minting Functions
mintPeggedToken(uint256 wrappedCollateralIn, address receiver, uint256 minPeggedOut)
Mints pegged tokens (haTokens) by depositing wrapped collateral.
Parameters:
wrappedCollateralIn: Amount of wrapped collateral to depositreceiver: Address to receive the minted pegged tokensminPeggedOut: Minimum amount of pegged tokens expected (slippage protection)
Returns:
peggedOut: Amount of pegged tokens minted
Effects:
- Transfers wrapped collateral from sender to contract
- Mints pegged tokens to receiver
- Applies fees based on current collateral ratio
- Updates
peggedTokenBalanceandunderlyingCollateral
mintLeveragedToken(uint256 wrappedCollateralIn, address receiver, uint256 minLeveragedOut)
Mints leveraged tokens (hsTokens) by depositing wrapped collateral.
Parameters:
wrappedCollateralIn: Amount of wrapped collateral to depositreceiver: Address to receive the minted leveraged tokensminLeveragedOut: Minimum amount of leveraged tokens expected (slippage protection)
Returns:
leveragedOut: Amount of leveraged tokens minted
Effects:
- Transfers wrapped collateral from sender to contract
- Mints leveraged tokens to receiver
- Applies fees or discounts based on current collateral ratio
- Updates
underlyingCollateral
Redemption Functions
redeemPeggedToken(uint256 peggedIn, address receiver, uint256 minWrappedCollateralOut)
Redeems pegged tokens (haTokens) for wrapped collateral.
Parameters:
peggedIn: Amount of pegged tokens to redeemreceiver: Address to receive the wrapped collateralminWrappedCollateralOut: Minimum amount of wrapped collateral expected (slippage protection)
Returns:
wrappedCollateralOut: Amount of wrapped collateral returned
Effects:
- Burns pegged tokens from sender
- Transfers wrapped collateral to receiver
- Applies fees or discounts based on current collateral ratio
- May request bonus from reserve pool if discount applies
- Updates
peggedTokenBalanceandunderlyingCollateral
redeemLeveragedToken(uint256 leveragedIn, address receiver, uint256 minWrappedCollateralOut)
Redeems leveraged tokens (hsTokens) for wrapped collateral.
Parameters:
leveragedIn: Amount of leveraged tokens to redeemreceiver: Address to receive the wrapped collateralminWrappedCollateralOut: Minimum amount of wrapped collateral expected (slippage protection)
Returns:
wrappedCollateralOut: Amount of wrapped collateral returned
Effects:
- Burns leveraged tokens from sender
- Transfers wrapped collateral to receiver
- Applies fees based on current collateral ratio
- Updates
underlyingCollateral
Fee-Free Functions (Restricted Access)
These functions are available only to addresses with ZERO_FEE_ROLE:
freeMintPeggedToken(uint256 wrappedCollateralIn, address receiver)freeRedeemPeggedToken(uint256 peggedForCollateral, uint256 peggedForLeveraged, address receiver)freeMintLeveragedToken(uint256 wrappedCollateralIn, address receiver)freeRedeemLeveragedToken(uint256 leveragedIn, address receiver)
Dry Run Functions
These view functions simulate minting/redemption operations without executing them:
mintPeggedTokenDryRun(uint256 wrappedCollateralIn)- Returns incentive ratio, fees, amounts, price, and rateredeemPeggedTokenDryRun(uint256 peggedIn)- Returns incentive ratio, fees, discounts, amounts, price, and ratemintLeveragedTokenDryRun(uint256 wrappedCollateralIn)- Returns incentive ratio, fees, discounts, amounts, price, and rateredeemLeveragedTokenDryRun(uint256 leveragedIn)- Returns incentive ratio, fees, amounts, price, and rate
View Functions
Price and Ratio Queries
collateralRatio() returns (uint256)- Current collateral ratio (collateral value / pegged token value)leverageRatio() returns (uint256)- Current leverage ratio (capped at 20x)peggedTokenPrice() returns (uint256)- Current price of pegged tokenleveragedTokenPrice() returns (uint256)- Current NAV of leveraged token
Incentive Ratio Queries
mintPeggedTokenIncentiveRatio() returns (int256)- Fee/discount ratio for minting pegged tokensredeemPeggedTokenIncentiveRatio() returns (int256)- Fee/discount ratio for redeeming pegged tokensmintLeveragedTokenIncentiveRatio() returns (int256)- Fee/discount ratio for minting leveraged tokensredeemLeveragedTokenIncentiveRatio() returns (int256)- Fee/discount ratio for redeeming leveraged tokens
Balance Queries
peggedTokenBalance() returns (uint256)- Total pegged tokens minted by this contractleveragedTokenBalance() returns (uint256)- Total supply of leveraged tokenscollateralTokenBalance() returns (uint256)- Total underlying collateral
Other View Functions
harvestable() returns (uint256)- Amount of wrapped collateral available for harvestingredeemPeggedForCollateralRatio(uint256 targetCollateralRatio)- Calculates how to split pegged redemption to achieve target CRconfig() returns (Config)- Returns the current incentive configuration
Configuration Functions (Owner Only)
updateConfig(Config calldata config_)- Updates fee/discount/disallow configurationupdatePriceOracle(address priceOracle_)- Updates the price oracle addressupdateFeeReceiver(address feeReceiver_)- Updates the fee receiver addressupdateReservePool(address reservePool_)- Updates the reserve pool addressreset()- Resets underlying collateral tracking (for accounting corrections)
Fee, Discount, and Disallow System
The contract implements a sophisticated incentive system based on collateral ratio bands:
- Positive values: Fees (taken from input/output)
- Negative values: Discounts (provided from reserve pool)
- Value == 1 ether: Disallow (action blocked at that collateral ratio)
Fees and discounts are calculated as definite integrals across collateral ratio boundaries, ensuring fairness regardless of transaction size.
Dependencies
- LEVERAGED_TOKEN: The leveraged token contract (MintableBurnableERC20)
- PEGGED_TOKEN: The pegged token contract (MintableBurnableERC20)
- WRAPPED_COLLATERAL_TOKEN: The wrapped collateral token (e.g., wstETH)
- priceOracle: Price oracle implementing
IWrappedPriceOracleinterface - reservePool: Reserve pool implementing
IReservePoolinterface (source of discounts) - feeReceiver: Address that receives protocol fees (typically TokenDistributor)
Security Considerations
- All mutating functions are protected by
nonReentrantmodifier - Price oracle provides min/mid/max prices for different use cases
- Minimum output amounts prevent excessive slippage
- Disallow mechanism can block actions at dangerous collateral ratios
- Reserve pool capacity limits discount amounts
- Leverage ratio is capped at 20x
- Contract uses UUPS upgradeable pattern (only owner can upgrade)