EndowmentController_v1) draws collateral from the reserve behind the reference segment by calling ReserveManager_v1, and sends the drawn collateral to a delegate, an address that the endowment admin sets.
The reserve manager also draws collateral against issuance tokens locked in positions (Overview). Endowment draws and those draws share one limit, the draw bound. The premium segments keep trading while endowment draws are made. The endowment controller is the only address that can make endowment draws, and ReserveManager_v1 records each draw against it so that the drawn amount can be restored.
Parts of an endowed market
A market is endowed when its
ReserveManager_v1 is initialized with an endowment controller address and an endowment admin address. The two addresses must be non-zero and different. Neither address has a setter, so both are fixed for the life of the reserve manager.
Setup
Initialization opens endowment setup on both the reserve manager and the curve. While setup is open:buy,buyFor,sellandsellTorevert.- Credit draws through the reserve manager (
openPosition,lockAndDraw,draw) revert. drawUnbackedReservesreverts.- The controller’s
armreverts.
Registration happens once. A second call reverts, and the curve’s reference-sell controller cannot be set a second time. Finalization cannot be undone: the reserve manager has no call that reopens setup.
EndowmentController_v1.initialize runs once, while setup is open. It reverts unless the controller’s configuration matches the reserve manager and curve it names and the reserve manager lists the controller as its expected controller.
Drawing
The endowment admin sets a delegate, arms the controller, and callsdraw on the controller with an amount. The controller calls drawUnbackedReserves on the reserve manager. The reserve manager checks the draw bound, adds the amount to the controller’s recorded draw, and has the curve transfer the collateral to the controller. In the same transaction, the controller sends the amount, plus any collateral it already held, to the delegate.
A draw does not change the curve’s virtual collateral supply, its segments or its prices. The collateral leaves the curve, and the reserve manager records it as outstanding draws.
Draw bound
A draw succeeds when total outstanding draws after the draw are at or below the reference price times the lower of supply and the reference segment’s size: where:- is the total of endowment draws not yet restored (
getTotalUnbackedReserveDrawn), in collateral - is the total of credit draws not yet repaid (
getTotalOutstandingReserves), in collateral - is the amount of this draw, in collateral
- is the reference price (
getReferencePrice), in collateral per token, 18 decimals - is the issuance token’s total supply
- is the reference segment’s size, its supply per step (
getReferenceMetrics)
_drawAgainst) check the same bound, so endowment draws and credit draws share one limit.
Example. A market has a reference segment of 1,000 tokens at a reference price of 1.00. Supply is 1,250. Earlier endowment draws total 300.00, and no credit is outstanding. The controller draws 500.00.
After the draw, a further draw of up to 200.00 succeeds, and a draw of 200.01 reverts.
Example. On the same curve, supply is 400 and no draws or credit are outstanding. The bound is 1.00 × min(400, 1,000) = 400.00. A draw of 500.00 reverts, and a draw of 400.00 succeeds.
Sells into the reference segment with outstanding draws
When a sell takes supply below the reference segment’s size, the curve shrinks the reference segment to the new supply in the same transaction (Markets and curves). On an endowed market, the new reference segment must still satisfy the draw bound with . If outstanding draws are above the reference price times the new supply, the sell reverts. Example. A market has a reference segment of 1,000 tokens at 1.00, supply of 1,000, and endowment draws of 800.00. Buyers paid 1.00 per token with a buy fee of 0, so the curve held 1,000.00 before the draws. The sell fee is 0.
At 850 supply, the largest sell that succeeds is 50 tokens, which takes supply to 800 and the curve’s collateral to 0.
The controller
The endowment admin operates the controller. Every function below reverts if called by any other address, exceptforwardSurplus.
The delegate is settable. To change it, the endowment admin disarms the controller, calls
setBeneficiary, and arms it again. The delegate starts unset: initialize reverts if the configuration names one.
Configuration fields not active in this version
ControllerConfig holds the addresses of the curve, reserve manager, collateral token, issuance token, freeze guardian and authorizer. It also has the fields pool, tracker, feeRecipient, excessTarget, forcedSaleExecutor, activationReserve, secondaryBps, minSync and feeBps. These fields are not active in this version. initialize reverts unless each of them is zero, and _isFullModeEnabled returns false.
Reference-sell switch
The curve has a reference-sell switch (setReferenceSellsClosed). Only the registered controller can call it, and the authorizer grants permission for this function only to ENDOWMENT_CONTROLLER_ROLE. The switch starts open.
While the switch is closed:
sellandsellTorevert. The check covers every sell to the curve, including sells that stay within the premium segments.buyandbuyForwork.- Endowment draws and credit draws work, within the draw bound.
- A new curve from
rebalanceSegments,elevateorreconfigureSegmentsreverts if it lowers the reference price or sets the reference segment’s size above supply.
EndowmentController_v1 in this version has no function that calls setReferenceSellsClosed. The switch therefore stays open, and sells to the curve follow the rules in Markets and curves and the draw bound above.
Restoration
restoreUnbackedReserves returns drawn collateral to the curve. The caller approves the reserve manager for the amount. The reserve manager takes the collateral from the caller, passes it to the curve, and lowers the caller’s recorded draw and the total by the same amount.
where:
- is the amount restored, in collateral
- is the amount the caller requests
- is the caller’s recorded draw (
getUnbackedDrawnBy)
The only address with a recorded endowment draw is the controller.
EndowmentController_v1 in this version has no function that calls restoreUnbackedReserves.
Parameters
Authority lists every role.
Scenarios
Edge cases
- Registration with prior exposure.
registerEndowmentControllerreverts if any issuance supply, endowment draw or credit draw exists. - Unbacked-draw flag and ceiling. The reserve manager’s unbacked-draw flag (
isUnbackedDrawsAllowed) and ceiling (getUnbackedDrawCeilingBps) are set at initialization and limitdrawUnbackedReserveswhen the reserve manager is initialized with no endowment controller. With the flag off, every call reverts. With the flag on, total outstanding unbacked draws must stay at or below the ceiling, in basis points of the lower of the virtual collateral supply and the recorded ceiling base. On an endowed market,drawUnbackedReserveschecks neither the flag nor the ceiling: only the registered endowment controller can draw, and the draw bound is the only limit on the amount. - Supply below the reference segment’s size. The bound uses supply, not the reference segment’s size.
- New curves.
rebalanceSegments,elevateandreconfigureSegmentsrevert if outstanding draws are above the new reference price times the lower of supply and the new reference segment’s size. - Restore with no recorded draw.
restoreUnbackedReservesfrom an address with no recorded draw returns without a transfer and emits no event. - Collateral sent to the controller. Collateral on the controller goes to the delegate on the next
draworforwardSurplus. - Last token sold. While outstanding draws exist, a sell that takes supply to 0 reverts.
Code
Source:
house-markets/contracts at 0ebbc89a (branch integration/v12-post-qa).