On an endowed market, a registered endowment controller (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, sell and sellTo revert.
  • Credit draws through the reserve manager (openPosition, lockAndDraw, draw) revert.
  • drawUnbackedReserves reverts.
  • The controller’s arm reverts.
The endowment admin then completes three steps, in this order. Each step reverts if called by any other address, and each reverts after setup is closed. 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 calls draw 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: U+L+a≤Pref⋅min⁡(s, Qref)U + L + a \le P_{\text{ref}} \cdot \min(s,\ Q_{\text{ref}}) where:
  • UU is the total of endowment draws not yet restored (getTotalUnbackedReserveDrawn), in collateral
  • LL is the total of credit draws not yet repaid (getTotalOutstandingReserves), in collateral
  • aa is the amount of this draw, in collateral
  • PrefP_{\text{ref}} is the reference price (getReferencePrice), in collateral per token, 18 decimals
  • ss is the issuance token’s total supply
  • QrefQ_{\text{ref}} is the reference segment’s size, its supply per step (getReferenceMetrics)
The right-hand side is rounded down. If the left-hand side is above it, the draw reverts. Credit draws on an endowed market (_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 a=0a = 0. 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, except forwardSurplus. 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:
  • sell and sellTo revert. The check covers every sell to the curve, including sells that stay within the premium segments.
  • buy and buyFor work.
  • Endowment draws and credit draws work, within the draw bound.
  • A new curve from rebalanceSegments, elevate or reconfigureSegments reverts if it lowers the reference price or sets the reference segment’s size above supply.
Closing the switch has no outstanding-draws condition. Opening it reverts while outstanding draws, U+LU + L, are above 0. A call that sets the switch to its existing state does nothing. 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 UU by the same amount. r=min⁡(a, d)r = \min(a,\ d) where:
  • rr is the amount restored, in collateral
  • aa is the amount the caller requests
  • dd is the caller’s recorded draw (getUnbackedDrawnBy)
The cap applies per address. A caller cannot lower another address’s recorded draw. A restore lowers UU, which adds the same amount of room under the draw bound. Example. An address has a recorded draw of 800.00 and requests a restore of 1,000.00. 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. registerEndowmentController reverts 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 limit drawUnbackedReserves when 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, drawUnbackedReserves checks 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, elevate and reconfigureSegments revert 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. restoreUnbackedReserves from 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 draw or forwardSurplus.
  • 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).