@agoric/inter-protocol 0.13.3 → 0.13.4-dev-d32a66a.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. package/README.md +26 -20
  2. package/bundles/bundle-auctioneer-js-meta.json +722 -0
  3. package/bundles/bundle-auctioneer.js +1 -0
  4. package/bundles/bundle-econCommitteeCharter-js-meta.json +514 -0
  5. package/bundles/bundle-econCommitteeCharter.js +1 -0
  6. package/bundles/bundle-feeDistributor-js-meta.json +458 -0
  7. package/bundles/bundle-feeDistributor.js +1 -1
  8. package/bundles/bundle-fluxAggregatorKit-js-meta.json +674 -0
  9. package/bundles/bundle-fluxAggregatorKit.js +1 -0
  10. package/bundles/bundle-psm-js-meta.json +666 -0
  11. package/bundles/bundle-psm.js +1 -1
  12. package/bundles/bundle-reserve-js-meta.json +662 -0
  13. package/bundles/bundle-reserve.js +1 -1
  14. package/bundles/bundle-scaledPriceAuthority-js-meta.json +542 -0
  15. package/bundles/bundle-scaledPriceAuthority.js +1 -1
  16. package/bundles/bundle-vaultFactory-js-meta.json +786 -0
  17. package/bundles/bundle-vaultFactory.js +1 -1
  18. package/exported.js +0 -2
  19. package/package.json +34 -31
  20. package/scripts/add-collateral-core.js +14 -4
  21. package/scripts/build-bundles.js +9 -2
  22. package/scripts/deploy-contracts.js +1 -4
  23. package/scripts/init-core.js +20 -38
  24. package/scripts/invite-committee-core.js +1 -1
  25. package/scripts/manual-price-feed.js +2 -2
  26. package/scripts/price-feed-core.js +7 -6
  27. package/scripts/start-local-chain.sh +84 -0
  28. package/src/auction/auctionBook.js +755 -0
  29. package/src/auction/auctioneer.js +720 -0
  30. package/src/auction/offerBook.js +221 -0
  31. package/src/auction/params.js +174 -0
  32. package/src/auction/scheduleMath.js +167 -0
  33. package/src/auction/scheduler.js +370 -0
  34. package/src/auction/sortedOffers.js +136 -0
  35. package/src/auction/util.js +55 -0
  36. package/src/clientSupport.js +324 -0
  37. package/src/collectFees.js +8 -14
  38. package/src/contractSupport.js +24 -68
  39. package/src/econCommitteeCharter.js +161 -77
  40. package/src/feeDistributor.js +60 -20
  41. package/src/index.js +2 -0
  42. package/src/interest-math.js +1 -4
  43. package/src/interest.js +20 -13
  44. package/src/price/README.md +57 -0
  45. package/src/price/fluxAggregatorContract.js +190 -0
  46. package/src/price/fluxAggregatorKit.js +375 -0
  47. package/src/price/priceOracleKit.js +127 -0
  48. package/src/price/roundsManager.js +726 -0
  49. package/src/proposals/addAssetToVault.js +89 -94
  50. package/src/proposals/committee-proposal.js +141 -40
  51. package/src/proposals/core-proposal.js +100 -167
  52. package/src/proposals/econ-behaviors.js +320 -564
  53. package/src/proposals/price-feed-proposal.js +175 -78
  54. package/src/proposals/startEconCommittee.js +25 -12
  55. package/src/proposals/startPSM.js +231 -211
  56. package/src/proposals/utils.js +31 -17
  57. package/src/psm/README.md +71 -0
  58. package/src/psm/psm.js +272 -160
  59. package/src/psm/types.js +2 -0
  60. package/src/reserve/assetReserve.js +56 -413
  61. package/src/reserve/assetReserveKit.js +303 -0
  62. package/src/reserve/doc.md +1 -3
  63. package/src/reserve/params.js +2 -5
  64. package/src/typeGuards.js +13 -0
  65. package/src/vaultFactory/Liquidation.md +100 -0
  66. package/src/vaultFactory/burn.js +2 -1
  67. package/src/vaultFactory/liquidation.js +270 -108
  68. package/src/vaultFactory/math.js +95 -0
  69. package/src/vaultFactory/orderedVaultStore.js +0 -1
  70. package/src/vaultFactory/params.js +133 -112
  71. package/src/vaultFactory/prioritizedVaults.js +36 -79
  72. package/src/vaultFactory/storeUtils.js +67 -9
  73. package/src/vaultFactory/type-imports.js +2 -0
  74. package/src/vaultFactory/types.js +22 -26
  75. package/src/vaultFactory/vault.js +772 -709
  76. package/src/vaultFactory/vaultDirector.js +480 -483
  77. package/src/vaultFactory/vaultFactory.js +99 -60
  78. package/src/vaultFactory/vaultHolder.js +121 -95
  79. package/src/vaultFactory/vaultKit.js +39 -31
  80. package/src/vaultFactory/vaultManager.js +1249 -868
  81. package/bundles/bundle-amm-meta.js +0 -618
  82. package/bundles/bundle-amm.js +0 -1
  83. package/bundles/bundle-feeDistributor-meta.js +0 -346
  84. package/bundles/bundle-interchainPool-meta.js +0 -534
  85. package/bundles/bundle-interchainPool.js +0 -1
  86. package/bundles/bundle-liquidateIncrementally-meta.js +0 -442
  87. package/bundles/bundle-liquidateIncrementally.js +0 -1
  88. package/bundles/bundle-liquidateMinimum-meta.js +0 -442
  89. package/bundles/bundle-liquidateMinimum.js +0 -1
  90. package/bundles/bundle-psm-meta.js +0 -538
  91. package/bundles/bundle-psmCharter-meta.js +0 -418
  92. package/bundles/bundle-psmCharter.js +0 -1
  93. package/bundles/bundle-reserve-meta.js +0 -542
  94. package/bundles/bundle-scaledPriceAuthority-meta.js +0 -442
  95. package/bundles/bundle-stakeFactory-meta.js +0 -574
  96. package/bundles/bundle-stakeFactory.js +0 -1
  97. package/bundles/bundle-vaultFactory-meta.js +0 -598
  98. package/scripts/add-initial-liquidity.js +0 -180
  99. package/src/collect.js +0 -13
  100. package/src/interchainPool.js +0 -135
  101. package/src/makeTracer.js +0 -36
  102. package/src/my-lien.js +0 -85
  103. package/src/proposals/demoIssuers.js +0 -685
  104. package/src/proposals/sim-behaviors.js +0 -40
  105. package/src/psm/psmCharter.js +0 -139
  106. package/src/stakeFactory/README.md +0 -62
  107. package/src/stakeFactory/attestation.js +0 -267
  108. package/src/stakeFactory/attestationTool.js +0 -66
  109. package/src/stakeFactory/constants.js +0 -16
  110. package/src/stakeFactory/params.js +0 -31
  111. package/src/stakeFactory/stakeFactory.js +0 -236
  112. package/src/stakeFactory/stakeFactoryKit.js +0 -455
  113. package/src/stakeFactory/stakeFactoryManager.js +0 -296
  114. package/src/stakeFactory/types.js +0 -42
  115. package/src/vaultFactory/liquidateIncrementally.js +0 -350
  116. package/src/vaultFactory/liquidateMinimum.js +0 -100
  117. package/src/vpool-xyk-amm/AttackersGuide.md +0 -89
  118. package/src/vpool-xyk-amm/addLiquidity.js +0 -222
  119. package/src/vpool-xyk-amm/addPool.js +0 -197
  120. package/src/vpool-xyk-amm/constantProduct/AMM-Trade.jpeg +0 -0
  121. package/src/vpool-xyk-amm/constantProduct/README.md +0 -204
  122. package/src/vpool-xyk-amm/constantProduct/calcFees.js +0 -99
  123. package/src/vpool-xyk-amm/constantProduct/calcSwapPrices.js +0 -85
  124. package/src/vpool-xyk-amm/constantProduct/core.js +0 -153
  125. package/src/vpool-xyk-amm/constantProduct/defaults.js +0 -5
  126. package/src/vpool-xyk-amm/constantProduct/getXY.js +0 -52
  127. package/src/vpool-xyk-amm/constantProduct/internal-types.js +0 -116
  128. package/src/vpool-xyk-amm/constantProduct/invariants.js +0 -43
  129. package/src/vpool-xyk-amm/constantProduct/swap.js +0 -272
  130. package/src/vpool-xyk-amm/constantProduct/types.js +0 -32
  131. package/src/vpool-xyk-amm/doublePool.js +0 -194
  132. package/src/vpool-xyk-amm/estimate.js +0 -155
  133. package/src/vpool-xyk-amm/multipoolMarketMaker.js +0 -520
  134. package/src/vpool-xyk-amm/params.js +0 -61
  135. package/src/vpool-xyk-amm/pool.js +0 -396
  136. package/src/vpool-xyk-amm/priceAuthority.js +0 -94
  137. package/src/vpool-xyk-amm/removeLiquidity.js +0 -31
  138. package/src/vpool-xyk-amm/singlePool.js +0 -73
  139. package/src/vpool-xyk-amm/swap.js +0 -69
  140. package/src/vpool-xyk-amm/types.js +0 -154
@@ -1,64 +1,49 @@
1
- // @ts-check
2
-
3
1
  import '@agoric/zoe/exported.js';
4
2
  import '@agoric/zoe/src/contracts/exported.js';
5
3
 
6
- import '@agoric/governance/src/exported.js';
7
- import { E } from '@endo/eventual-send';
4
+ import '@agoric/governance/exported.js';
8
5
 
9
- import { fit, keyEQ, M, makeScalarMap } from '@agoric/store';
6
+ import { AmountMath, AmountShape, BrandShape, IssuerShape } from '@agoric/ertp';
7
+ import { GovernorFacetShape } from '@agoric/governance/src/typeGuards.js';
8
+ import { makeTracer } from '@agoric/internal';
9
+ import { M, mustMatch } from '@agoric/store';
10
+ import {
11
+ prepareExoClassKit,
12
+ provide,
13
+ provideDurableMapStore,
14
+ } from '@agoric/vat-data';
15
+ import { assertKeywordName } from '@agoric/zoe/src/cleanProposal.js';
10
16
  import {
11
- assertProposalShape,
17
+ atomicRearrange,
12
18
  getAmountIn,
13
19
  getAmountOut,
20
+ makeRatioFromAmounts,
21
+ makeRecorderTopic,
22
+ provideEmptySeat,
23
+ SubscriberShape,
24
+ TopicsRecordShape,
25
+ unitAmount,
14
26
  } from '@agoric/zoe/src/contractSupport/index.js';
15
- import { makeRatioFromAmounts } from '@agoric/zoe/src/contractSupport/ratio.js';
27
+ import { E } from '@endo/eventual-send';
16
28
  import { Far } from '@endo/marshal';
17
-
18
- import { AmountMath } from '@agoric/ertp';
19
- import { makeStoredPublisherKit, observeIteration } from '@agoric/notifier';
29
+ import { makeCollectFeesInvitation } from '../collectFees.js';
20
30
  import {
21
- defineDurableKindMulti,
22
- makeKindHandle,
23
- makeScalarBigMapStore,
24
- } from '@agoric/vat-data';
25
- import { assertKeywordName } from '@agoric/zoe/src/cleanProposal.js';
26
- import { makeMakeCollectFeesInvitation } from '../collectFees.js';
27
- import { makeMetricsPublisherKit } from '../contractSupport.js';
31
+ setWakeupsForNextAuction,
32
+ watchForGovernanceChange,
33
+ } from './liquidation.js';
28
34
  import {
29
- CHARGING_PERIOD_KEY,
30
- makeVaultParamManager,
31
- RECORDING_PERIOD_KEY,
35
+ provideVaultParamManagers,
32
36
  SHORTFALL_INVITATION_KEY,
33
37
  vaultParamPattern,
34
38
  } from './params.js';
35
- import { makeVaultManager } from './vaultManager.js';
36
-
37
- const { details: X, quote: q } = assert;
38
-
39
- /** @typedef {{
40
- * debtMint: ZCFMint<'nat'>,
41
- * directorParamManager: import('@agoric/governance/src/contractGovernance/typedParamManager').TypedParamManager<import('./params.js').VaultDirectorParams>,
42
- * marshaller: ERef<Marshaller>,
43
- * metricsPublication: IterationObserver<MetricsNotification>
44
- * metricsSubscription: StoredSubscription<MetricsNotification>
45
- * shortfallReporter: import('../reserve/assetReserve.js').ShortfallReporter,
46
- * storageNode: ERef<StorageNode>,
47
- * vaultParamManagers: Store<Brand, import('./params.js').VaultParamManager>,
48
- * zcf: import('./vaultFactory.js').VaultFactoryZCF,
49
- * }} Ephemera
50
- */
39
+ import {
40
+ prepareVaultManagerKit,
41
+ provideAndStartVaultManagerKits,
42
+ } from './vaultManager.js';
51
43
 
52
- /**
53
- * Ephemera is the state we cannot (or merely need not) keep durably. For
54
- * vaultDirector we can keep it in module scope because there is (exactly) one
55
- * vaultDirector per vaultFactory contract and (exactly) one contract per vat.
56
- *
57
- * @type {Ephemera}
58
- */
59
- // @ts-expect-error not actually full until after initState
60
- // UNTIL resolution to https://github.com/Agoric/agoric-sdk/issues/5759
61
- const ephemera = {};
44
+ const { Fail, quote: q } = assert;
45
+
46
+ const trace = makeTracer('VD', true);
62
47
 
63
48
  /**
64
49
  * @typedef {{
@@ -67,513 +52,525 @@ const ephemera = {};
67
52
  * }} MetricsNotification
68
53
  *
69
54
  * @typedef {Readonly<{
70
- * collateralTypes: Store<Brand,VaultManager>,
71
- * mintSeat: ZCFSeat,
72
- * rewardPoolSeat: ZCFSeat,
73
- * shortfallInvitation: Invitation,
74
55
  * }>} ImmutableState
75
56
  *
76
57
  * @typedef {{
77
- * managerCounter: number,
78
58
  * }} MutableState
79
59
  *
80
60
  * @typedef {ImmutableState & MutableState} State
81
61
  *
82
- * @typedef {{
62
+ * @typedef {{
83
63
  * burnDebt: BurnDebt,
84
- * getGovernedParams: () => import('./vaultManager.js').GovernedParamGetters,
85
- * mintAndReallocate: MintAndReallocate,
64
+ * getGovernedParams: (collateralBrand: Brand) => import('./vaultManager.js').GovernedParamGetters,
65
+ * mintAndTransfer: MintAndTransfer,
86
66
  * getShortfallReporter: () => Promise<import('../reserve/assetReserve.js').ShortfallReporter>,
87
67
  * }} FactoryPowersFacet
88
68
  *
89
69
  * @typedef {Readonly<{
90
70
  * state: State;
91
- * facets: import('@agoric/vat-data/src/types').KindFacets<typeof behavior>;
92
71
  * }>} MethodContext
72
+ *
73
+ * @typedef {import('@agoric/governance/src/contractGovernance/typedParamManager').TypedParamManager<import('./params.js').VaultDirectorParams>} VaultDirectorParamManager
93
74
  */
94
75
 
95
- /**
96
- * @param {ERef<ZoeService>} zoe
97
- * @param {Ephemera['directorParamManager']} paramMgr
98
- * @param {import('../reserve/assetReserve.js').ShortfallReporter} [oldShortfallReporter]
99
- * @param {ERef<Invitation>} [oldInvitation]
100
- * @returns {Promise<{
101
- * shortfallInvitation: ERef<Invitation>,
102
- * shortfallReporter: import('../reserve/assetReserve.js').ShortfallReporter,
103
- * }>}
104
- */
105
- const updateShortfallReporter = async (
106
- zoe,
107
- paramMgr,
108
- oldShortfallReporter,
109
- oldInvitation,
110
- ) => {
111
- const newInvitation = paramMgr.getInternalParamValue(
112
- SHORTFALL_INVITATION_KEY,
113
- );
114
-
115
- if (newInvitation !== oldInvitation) {
116
- return {
117
- // @ts-expect-error cast
118
- shortfallReporter: E(E(zoe).offer(newInvitation)).getOfferResult(),
119
- shortfallInvitation: newInvitation,
120
- };
121
- } else {
122
- assert(
123
- oldShortfallReporter,
124
- 'updateShortFallReported called with repeat invitation and no oldShortfallReporter',
125
- );
126
- return {
127
- shortfallReporter: oldShortfallReporter,
128
- shortfallInvitation: oldInvitation,
129
- };
130
- }
131
- };
132
-
133
- /**
134
- * @param {Pick<State, 'collateralTypes' | 'rewardPoolSeat'>} state
135
- * @returns {MetricsNotification}
136
- */
137
- const metricsOf = state => {
138
- return harden({
139
- collaterals: Array.from(state.collateralTypes.keys()),
140
- rewardPoolAllocation: state.rewardPoolSeat.getCurrentAllocation(),
141
- });
142
- };
76
+ const shortfallInvitationKey = 'shortfallInvitation';
143
77
 
144
78
  /**
145
- * @param {Ephemera['zcf']} zcf
146
- * @param {Ephemera['directorParamManager']} directorParamManager
147
- * @param {Ephemera['debtMint']} debtMint
79
+ * @param {import('@agoric/ertp').Baggage} baggage
80
+ * @param {import('./vaultFactory.js').VaultFactoryZCF} zcf
81
+ * @param {VaultDirectorParamManager} directorParamManager
82
+ * @param {ZCFMint<"nat">} debtMint
83
+ * @param {ERef<import('@agoric/time/src/types').TimerService>} timer
84
+ * @param {ERef<import('../auction/auctioneer.js').AuctioneerPublicFacet>} auctioneer
148
85
  * @param {ERef<StorageNode>} storageNode
149
86
  * @param {ERef<Marshaller>} marshaller
150
- * @returns {State}
87
+ * @param {import('@agoric/zoe/src/contractSupport/recorder.js').MakeRecorderKit} makeRecorderKit
88
+ * @param {import('@agoric/zoe/src/contractSupport/recorder.js').MakeERecorderKit} makeERecorderKit
151
89
  */
152
- const initState = (
90
+ export const prepareVaultDirector = (
91
+ baggage,
153
92
  zcf,
154
93
  directorParamManager,
155
94
  debtMint,
95
+ timer,
96
+ auctioneer,
156
97
  storageNode,
157
98
  marshaller,
99
+ makeRecorderKit,
100
+ makeERecorderKit,
158
101
  ) => {
159
- /** For temporary staging of newly minted tokens */
160
- const { zcfSeat: mintSeat } = zcf.makeEmptySeatKit();
161
- const { zcfSeat: rewardPoolSeat } = zcf.makeEmptySeatKit();
102
+ /** @type {import('../reserve/assetReserve.js').ShortfallReporter} */
103
+ let shortfallReporter;
162
104
 
163
- const collateralTypes = makeScalarBigMapStore('collateralTypes', {
164
- durable: true,
165
- });
105
+ /** For holding newly minted tokens until transferred */
106
+ const { zcfSeat: mintSeat } = zcf.makeEmptySeatKit();
166
107
 
167
- // Non-durable map because param managers aren't durable.
168
- // In the event they're needed they can be reconstructed from contract terms and off-chain data.
169
- const vaultParamManagers = makeScalarMap('vaultParamManagers');
108
+ const rewardPoolSeat = provideEmptySeat(zcf, baggage, 'rewardPoolSeat');
170
109
 
171
- const { metricsPublication, metricsSubscription } = makeMetricsPublisherKit(
172
- storageNode,
173
- marshaller,
110
+ /** @type {MapStore<Brand, number>} index of manager for the given collateral */
111
+ const collateralManagers = provideDurableMapStore(
112
+ baggage,
113
+ 'collateralManagers',
174
114
  );
175
115
 
176
- Object.assign(ephemera, {
177
- debtMint,
178
- directorParamManager,
179
- marshaller,
180
- metricsPublication,
181
- // Subscription can't yet be held durably https://github.com/Agoric/agoric-sdk/issues/4567
182
- metricsSubscription,
183
- storageNode,
184
- vaultParamManagers,
185
- zcf,
186
- });
187
-
188
- return {
189
- collateralTypes,
190
- managerCounter: 0,
191
- mintSeat,
192
- rewardPoolSeat,
193
- // @ts-expect-error defined in finish()
194
- shortfallInvitation: undefined,
195
- };
196
- };
197
-
198
- /**
199
- * Make a loan in the vaultManager based on the collateral type.
200
- *
201
- * @deprecated
202
- * @param {MethodContext} context
203
- */
204
- const makeVaultInvitation = ({ state }) => {
205
- const { zcf } = ephemera;
206
-
207
- const { collateralTypes } = state;
208
-
209
- /** @param {ZCFSeat} seat */
210
- const makeVaultHook = async seat => {
211
- assertProposalShape(seat, {
212
- give: { Collateral: null },
213
- want: { Minted: null },
214
- });
215
- const {
216
- give: { Collateral: collateralAmount },
217
- want: { Minted: requestedAmount },
218
- } = seat.getProposal();
219
- const { brand: brandIn } = collateralAmount;
220
- collateralTypes.has(brandIn) ||
221
- assert.fail(X`Not a supported collateral type ${brandIn}`);
222
-
223
- assert(
224
- AmountMath.isGTE(
225
- requestedAmount,
226
- ephemera.directorParamManager.getMinInitialDebt(),
227
- ),
228
- X`The request must be for at least ${
229
- ephemera.directorParamManager.getMinInitialDebt().value
230
- }. ${requestedAmount.value} is too small`,
231
- );
116
+ // Non-durable map because param managers aren't durable.
117
+ // In the event they're needed they can be reconstructed from contract terms and off-chain data.
118
+ /** a powerful object; can modify parameters */
119
+ const vaultParamManagers = provideVaultParamManagers(baggage, marshaller);
232
120
 
233
- /** @type {VaultManager} */
234
- const mgr = collateralTypes.get(brandIn);
235
- return mgr.makeVaultKit(seat);
236
- };
237
- return zcf.makeInvitation(makeVaultHook, 'MakeVault');
238
- };
121
+ const metricsNode = E(storageNode).makeChildNode('metrics');
239
122
 
240
- /**
241
- * @deprecated get `collaterals` list from metrics
242
- * @param {MethodContext} context
243
- */
244
- const getCollaterals = async ({ state }) => {
245
- const { collateralTypes } = state;
246
- // should be collateralTypes.map((vm, brand) => ({
247
- return harden(
248
- Promise.all(
249
- [...collateralTypes.entries()].map(async ([brand, vm]) => {
250
- const priceQuote = await vm.getCollateralQuote();
251
- return {
252
- brand,
253
- interestRate: vm.getGovernedParams().getInterestRate(),
254
- liquidationMargin: vm.getGovernedParams().getLiquidationMargin(),
255
- stabilityFee: vm.getGovernedParams().getLoanFee(),
256
- marketPrice: makeRatioFromAmounts(
257
- getAmountOut(priceQuote),
258
- getAmountIn(priceQuote),
259
- ),
260
- };
261
- }),
123
+ const metricsKit = makeERecorderKit(
124
+ metricsNode,
125
+ /** @type {import('@agoric/zoe/src/contractSupport/recorder.js').TypedMatcher<MetricsNotification>} */ (
126
+ M.any()
262
127
  ),
263
128
  );
264
- };
265
- /**
266
- * @param {Ephemera['directorParamManager']} directorParamManager
267
- */
268
- const getLiquidationConfig = directorParamManager => ({
269
- install: directorParamManager.getLiquidationInstall(),
270
- terms: directorParamManager.getLiquidationTerms(),
271
- });
272
129
 
273
- /**
274
- *
275
- * @param {Ephemera['directorParamManager']} govParams
276
- * @param {VaultManager} vaultManager
277
- * @param {Installation<unknown>} oldInstall
278
- * @param {unknown} oldTerms
279
- */
280
- const watchGovernance = (govParams, vaultManager, oldInstall, oldTerms) => {
281
- const subscription = govParams.getSubscription();
282
- void observeIteration(subscription, {
283
- updateState(_paramUpdate) {
284
- const { install, terms } = getLiquidationConfig(govParams);
285
- if (install === oldInstall && keyEQ(terms, oldTerms)) {
286
- return;
287
- }
288
- oldInstall = install;
289
- oldTerms = terms;
290
- vaultManager
291
- .setupLiquidator(install, terms)
292
- .catch(e => console.error('Failed to setup liquidator', e));
293
- },
294
- });
295
- };
130
+ const managersNode = E(storageNode).makeChildNode('managers');
296
131
 
297
- /** @type {import('@agoric/vat-data/src/types').FunctionsPlusContext<MethodContext, VaultFactoryCreatorFacet>} */
298
- const machineBehavior = {
299
- // TODO move this under governance #3924
300
132
  /**
301
- * @param {MethodContext} context
302
- * @param {Issuer} collateralIssuer
303
- * @param {Keyword} collateralKeyword
304
- * @param {VaultManagerParamValues} initialParamValues
133
+ * @returns {MetricsNotification}
305
134
  */
306
- addVaultType: async (
307
- { state, facets },
308
- collateralIssuer,
309
- collateralKeyword,
310
- initialParamValues,
311
- ) => {
312
- const {
313
- debtMint,
314
- vaultParamManagers,
315
- directorParamManager,
316
- marshaller,
317
- storageNode,
318
- zcf,
319
- } = ephemera;
320
- const { collateralTypes, mintSeat, rewardPoolSeat } = state;
321
- fit(collateralIssuer, M.remotable(), 'collateralIssuer');
322
- assertKeywordName(collateralKeyword);
323
- fit(initialParamValues, vaultParamPattern, 'initialParamValues');
324
- await zcf.saveIssuer(collateralIssuer, collateralKeyword);
325
- const collateralBrand = zcf.getBrandForIssuer(collateralIssuer);
326
- // We create only one vault per collateralType.
327
- !collateralTypes.has(collateralBrand) ||
328
- assert.fail(
329
- X`Collateral brand ${q(collateralBrand)} has already been added`,
330
- );
331
-
332
- const managerStorageNode =
333
- storageNode &&
334
- E(storageNode).makeChildNode(`manager${state.managerCounter}`);
335
- state.managerCounter += 1;
336
-
337
- /** a powerful object; can modify parameters */
338
- const vaultParamManager = makeVaultParamManager(
339
- makeStoredPublisherKit(managerStorageNode, marshaller, 'governance'),
340
- initialParamValues,
135
+ const sampleMetrics = () => {
136
+ return harden({
137
+ collaterals: Array.from(collateralManagers.keys()),
138
+ rewardPoolAllocation: rewardPoolSeat.getCurrentAllocation(),
139
+ });
140
+ };
141
+ const writeMetrics = () => E(metricsKit.recorderP).write(sampleMetrics());
142
+
143
+ const updateShortfallReporter = async () => {
144
+ const oldInvitation = baggage.has(shortfallInvitationKey)
145
+ ? baggage.get(shortfallInvitationKey)
146
+ : undefined;
147
+ const newInvitation = await directorParamManager.getInternalParamValue(
148
+ SHORTFALL_INVITATION_KEY,
341
149
  );
342
- vaultParamManagers.init(collateralBrand, vaultParamManager);
343
150
 
344
- const { timerService } = zcf.getTerms();
345
- const startTimeStamp = await E(timerService).getCurrentTimestamp();
151
+ if (newInvitation === oldInvitation) {
152
+ shortfallReporter ||
153
+ Fail`updateShortFallReported called with repeat invitation and no prior shortfallReporter`;
154
+ return;
155
+ }
156
+
157
+ // Update the values
158
+ const zoe = zcf.getZoeService();
159
+ // @ts-expect-error cast
160
+ shortfallReporter = E(E(zoe).offer(newInvitation)).getOfferResult();
161
+ if (oldInvitation === undefined) {
162
+ baggage.init(shortfallInvitationKey, newInvitation);
163
+ } else {
164
+ baggage.set(shortfallInvitationKey, newInvitation);
165
+ }
166
+ };
346
167
 
168
+ const factoryPowers = Far('vault factory powers', {
347
169
  /**
348
- * We provide an easy way for the vaultManager to add rewards to
349
- * the rewardPoolSeat, without directly exposing the rewardPoolSeat to them.
170
+ * Get read-only params for this manager and its director. This grants all
171
+ * managers access to params from all managers. It's not POLA but it's a
172
+ * public authority and it reduces the number of distinct power objects to
173
+ * create.
350
174
  *
351
- * @type {MintAndReallocate}
175
+ * @param {Brand} brand
352
176
  */
353
- const mintAndReallocate = (toMint, fee, seat, ...otherSeats) => {
177
+ getGovernedParams: brand => {
178
+ const vaultParamManager = vaultParamManagers.get(brand);
179
+ return Far('vault manager param manager', {
180
+ // merge director and manager params
181
+ ...directorParamManager.readonly(),
182
+ ...vaultParamManager.readonly(),
183
+ // redeclare these getters as to specify the kind of the Amount
184
+ getMinInitialDebt: /** @type {() => Amount<'nat'>} */ (
185
+ directorParamManager.readonly().getMinInitialDebt
186
+ ),
187
+ getDebtLimit: /** @type {() => Amount<'nat'>} */ (
188
+ vaultParamManager.readonly().getDebtLimit
189
+ ),
190
+ });
191
+ },
192
+
193
+ /**
194
+ * Let the manager add rewards to the rewardPoolSeat without
195
+ * exposing the rewardPoolSeat to them.
196
+ *
197
+ * @type {MintAndTransfer}
198
+ */
199
+ mintAndTransfer: (mintReceiver, toMint, fee, nonMintTransfers) => {
354
200
  const kept = AmountMath.subtract(toMint, fee);
355
201
  debtMint.mintGains(harden({ Minted: toMint }), mintSeat);
202
+ /** @type {import('@agoric/zoe/src/contractSupport/atomicTransfer.js').TransferPart[]} */
203
+ const transfers = [
204
+ ...nonMintTransfers,
205
+ [mintSeat, rewardPoolSeat, { Minted: fee }],
206
+ [mintSeat, mintReceiver, { Minted: kept }],
207
+ ];
356
208
  try {
357
- rewardPoolSeat.incrementBy(
358
- mintSeat.decrementBy(harden({ Minted: fee })),
359
- );
360
- seat.incrementBy(mintSeat.decrementBy(harden({ Minted: kept })));
361
- zcf.reallocate(rewardPoolSeat, mintSeat, seat, ...otherSeats);
209
+ atomicRearrange(zcf, harden(transfers));
362
210
  } catch (e) {
363
- console.error('mintAndReallocate caught', e);
364
- mintSeat.clear();
365
- rewardPoolSeat.clear();
366
- // Make best efforts to burn the newly minted tokens, for hygiene.
367
- // That only relies on the internal mint, so it cannot fail without
368
- // there being much larger problems. There's no risk of tokens being
369
- // stolen here because the staging for them was already cleared.
211
+ console.error('mintAndTransfer failed to rearrange', e);
212
+ // If the rearrange fails, burn the newly minted tokens.
213
+ // Assume this won't fail because it relies on the internal mint.
214
+ // (Failure would imply much larger problems.)
370
215
  debtMint.burnLosses(harden({ Minted: toMint }), mintSeat);
371
216
  throw e;
372
- } finally {
373
- // Note that if this assertion may fail because of an error in the
374
- // try{} block, but that error won't be thrown because this executes
375
- // before the catch that rethrows it.
376
- assert(
377
- Object.values(mintSeat.getCurrentAllocation()).every(a =>
378
- AmountMath.isEmpty(a),
379
- ),
380
- X`Stage should be empty of Minted`,
381
- );
382
217
  }
383
- facets.machine.updateMetrics();
384
- };
385
-
218
+ void writeMetrics();
219
+ },
220
+ getShortfallReporter: async () => {
221
+ await updateShortfallReporter();
222
+ return shortfallReporter;
223
+ },
386
224
  /**
387
225
  * @param {Amount<'nat'>} toBurn
388
226
  * @param {ZCFSeat} seat
389
227
  */
390
- const burnDebt = (toBurn, seat) => {
228
+ burnDebt: (toBurn, seat) => {
391
229
  debtMint.burnLosses(harden({ Minted: toBurn }), seat);
392
- };
230
+ },
231
+ });
393
232
 
394
- const { loanTimingParams } = zcf.getTerms();
233
+ const makeVaultManagerKit = prepareVaultManagerKit(baggage, {
234
+ makeERecorderKit,
235
+ makeRecorderKit,
236
+ marshaller,
237
+ factoryPowers,
238
+ zcf,
239
+ });
395
240
 
396
- const factoryPowers = Far('vault factory powers', {
397
- getGovernedParams: () => ({
398
- ...vaultParamManager.readonly(),
399
- getChargingPeriod: () => loanTimingParams[CHARGING_PERIOD_KEY].value,
400
- getRecordingPeriod: () => loanTimingParams[RECORDING_PERIOD_KEY].value,
401
- }),
402
- mintAndReallocate,
403
- getShortfallReporter: async () => {
404
- const reporterKit = await updateShortfallReporter(
405
- zcf.getZoeService(),
406
- directorParamManager,
407
- ephemera.shortfallReporter,
408
- state.shortfallInvitation,
409
- );
410
- return reporterKit.shortfallReporter;
411
- },
412
- burnDebt,
413
- });
241
+ const vaultManagers = provideAndStartVaultManagerKits(baggage);
414
242
 
415
- const vm = makeVaultManager(
416
- zcf,
417
- debtMint,
418
- collateralBrand,
419
- zcf.getTerms().priceAuthority,
420
- factoryPowers,
421
- timerService,
422
- startTimeStamp,
423
- managerStorageNode,
424
- ephemera.marshaller,
425
- );
426
- collateralTypes.init(collateralBrand, vm);
427
- const { install, terms } = getLiquidationConfig(directorParamManager);
428
- await vm.setupLiquidator(install, terms);
429
- watchGovernance(directorParamManager, vm, install, terms);
430
- facets.machine.updateMetrics();
431
- return vm;
432
- },
433
- getCollaterals,
434
- /** @param {MethodContext} context */
435
- makeCollectFeesInvitation: ({ state }) => {
436
- const { debtMint, zcf } = ephemera;
437
- const { rewardPoolSeat } = state;
438
- return makeMakeCollectFeesInvitation(
439
- zcf,
440
- rewardPoolSeat,
441
- debtMint.getIssuerRecord().brand,
442
- 'Minted',
443
- ).makeCollectFeesInvitation();
444
- },
445
- getContractGovernor: () => ephemera.zcf.getTerms().electionManager,
446
- /** @param {MethodContext} context */
447
- updateMetrics: ({ state }) => {
448
- ephemera.metricsPublication.updateState(metricsOf(harden(state)));
449
- },
450
-
451
- // XXX accessors for tests
452
- /** @param {MethodContext} context */
453
- getRewardAllocation: ({ state }) =>
454
- state.rewardPoolSeat.getCurrentAllocation(),
455
- };
243
+ /** @type {(brand: Brand) => VaultManager} */
244
+ const managerForCollateral = brand => {
245
+ const managerIndex = collateralManagers.get(brand);
246
+ const manager = vaultManagers.get(managerIndex).self;
247
+ manager || Fail`no manager ${managerIndex} for collateral ${brand}`;
248
+ return manager;
249
+ };
456
250
 
457
- const creatorBehavior = {
458
- getParamMgrRetriever: () =>
459
- Far('paramManagerRetriever', {
460
- /** @param {VaultFactoryParamPath} paramPath */
461
- get: paramPath => {
462
- if (paramPath.key === 'governedParams') {
463
- return ephemera.directorParamManager;
464
- } else if (paramPath.key.collateralBrand) {
465
- return ephemera.vaultParamManagers.get(paramPath.key.collateralBrand);
466
- } else {
467
- assert.fail('Unsupported paramPath');
468
- }
469
- },
470
- }),
471
- /**
472
- * @param {MethodContext} context
473
- * @param {string} name
474
- */
475
- getInvitation: (context, name) =>
476
- ephemera.directorParamManager.getInternalParamValue(name),
477
- /** @param {MethodContext} context */
478
- getLimitedCreatorFacet: context => context.facets.machine,
479
- getGovernedApis: () => harden({}),
480
- getGovernedApiNames: () => harden({}),
481
- };
251
+ // TODO helper to make all the topics at once
252
+ const topics = harden({
253
+ metrics: makeRecorderTopic('Vault Factory metrics', metricsKit),
254
+ });
255
+
256
+ const allManagersDo = fn => {
257
+ for (const managerIndex of collateralManagers.values()) {
258
+ const vm = vaultManagers.get(managerIndex).self;
259
+ fn(vm);
260
+ }
261
+ };
262
+
263
+ const makeWaker = (name, func) => {
264
+ return Far(name, {
265
+ wake: timestamp => func(timestamp),
266
+ });
267
+ };
482
268
 
483
- const publicBehavior = {
484
269
  /**
485
- * @param {MethodContext} context
486
- * @param {Brand} brandIn
270
+ * @returns {State}
487
271
  */
488
- getCollateralManager: ({ state }, brandIn) => {
489
- const { collateralTypes } = state;
490
- collateralTypes.has(brandIn) ||
491
- assert.fail(X`Not a supported collateral type ${brandIn}`);
492
- /** @type {VaultManager} */
493
- return collateralTypes.get(brandIn).getPublicFacet();
494
- },
495
- getMetrics: () => ephemera.metricsSubscription,
496
-
497
- /** @deprecated use getCollateralManager and then makeVaultInvitation instead */
498
- makeLoanInvitation: makeVaultInvitation,
499
- /** @deprecated use getCollateralManager and then makeVaultInvitation instead */
500
- makeVaultInvitation,
501
- getCollaterals,
502
- getRunIssuer: () => ephemera.debtMint.getIssuerRecord().issuer,
272
+ const initState = () => {
273
+ return {};
274
+ };
275
+
503
276
  /**
504
- * subscription for the paramManager for a particular vaultManager
277
+ * "Director" of the vault factory, overseeing "vault managers".
505
278
  *
506
- * @param {MethodContext} context
507
- * @param {{ collateralBrand: Brand }} selector
279
+ * @param {import('./vaultFactory.js').VaultFactoryZCF} zcf
280
+ * @param {VaultDirectorParamManager} directorParamManager
281
+ * @param {ZCFMint<"nat">} debtMint
508
282
  */
509
- getSubscription: (context, { collateralBrand }) =>
510
- ephemera.vaultParamManagers.get(collateralBrand).getSubscription(),
511
- /**
512
- * subscription for the paramManager for the vaultFactory's electorate
513
- */
514
- getElectorateSubscription: () =>
515
- ephemera.directorParamManager.getSubscription(),
516
- /**
517
- * @param {MethodContext} context
518
- * @param {{ collateralBrand: Brand }} selector
519
- */
520
- getGovernedParams: (context, { collateralBrand }) =>
521
- // TODO use named getters of TypedParamManager
522
- ephemera.vaultParamManagers.get(collateralBrand).getParams(),
523
- /**
524
- * @returns {Promise<GovernorPublic>}
525
- */
526
- getContractGovernor: () =>
527
- // PERF consider caching
528
- E(ephemera.zcf.getZoeService()).getPublicFacet(
529
- ephemera.zcf.getTerms().electionManager,
530
- ),
531
- /**
532
- * @param {MethodContext} context
533
- * @param {string} name
534
- */
535
- getInvitationAmount: (context, name) =>
536
- ephemera.directorParamManager.getInvitationAmount(name),
537
- };
538
-
539
- const behavior = {
540
- creator: creatorBehavior,
541
- machine: machineBehavior,
542
- public: publicBehavior,
543
- };
544
-
545
- /** @param {MethodContext} context */
546
- const finish = async ({ state }) => {
547
- const { shortfallReporter, shortfallInvitation } =
548
- await updateShortfallReporter(
549
- ephemera.zcf.getZoeService(),
550
- ephemera.directorParamManager,
551
- );
552
- ephemera.shortfallReporter = shortfallReporter;
553
- // @ts-expect-error write once
554
- state.shortfallInvitation = shortfallInvitation;
283
+ const makeVaultDirector = prepareExoClassKit(
284
+ baggage,
285
+ 'VaultDirector',
286
+ {
287
+ creator: M.interface('creator', {
288
+ ...GovernorFacetShape,
289
+ }),
290
+ machine: M.interface('machine', {
291
+ addVaultType: M.call(IssuerShape, M.string(), M.record()).returns(
292
+ M.promise(),
293
+ ),
294
+ makeCollectFeesInvitation: M.call().returns(M.promise()),
295
+ getRewardAllocation: M.call().returns({ Minted: AmountShape }),
296
+ makePriceLockWaker: M.call().returns(M.remotable('TimerWaker')),
297
+ makeLiquidationWaker: M.call().returns(M.remotable('TimerWaker')),
298
+ makeReschedulerWaker: M.call().returns(M.remotable('TimerWaker')),
299
+ }),
300
+ public: M.interface('public', {
301
+ getCollateralManager: M.call(BrandShape).returns(M.remotable()),
302
+ getCollaterals: M.call().returns(M.promise()),
303
+ getMetrics: M.call().returns(SubscriberShape),
304
+ getRunIssuer: M.call().returns(IssuerShape),
305
+ getSubscription: M.call({ collateralBrand: BrandShape }).returns(
306
+ SubscriberShape,
307
+ ),
308
+ getElectorateSubscription: M.call().returns(SubscriberShape),
309
+ getGovernedParams: M.call({ collateralBrand: BrandShape }).returns(
310
+ M.record(),
311
+ ),
312
+ getInvitationAmount: M.call(M.string()).returns(AmountShape),
313
+ getPublicTopics: M.call().returns(TopicsRecordShape),
314
+ }),
315
+ helper: M.interface('helper', {
316
+ resetWakeupsForNextAuction: M.call().returns(M.promise()),
317
+ start: M.call().returns(M.promise()),
318
+ }),
319
+ },
320
+ initState,
321
+ {
322
+ creator: {
323
+ getParamMgrRetriever: () =>
324
+ Far('paramManagerRetriever', {
325
+ /** @param {VaultFactoryParamPath} paramPath */
326
+ get: (
327
+ paramPath = { key: /** @type {const} */ 'governedParams' },
328
+ ) => {
329
+ if (paramPath.key === 'governedParams') {
330
+ return directorParamManager;
331
+ } else if (paramPath.key.collateralBrand) {
332
+ return vaultParamManagers.get(paramPath.key.collateralBrand);
333
+ } else {
334
+ assert.fail('Unsupported paramPath');
335
+ }
336
+ },
337
+ }),
338
+ /**
339
+ * @param {string} name
340
+ */
341
+ getInvitation(name) {
342
+ return directorParamManager.getInternalParamValue(name);
343
+ },
344
+ getLimitedCreatorFacet() {
345
+ return this.facets.machine;
346
+ },
347
+ /** @returns {ERef<GovernedApis>} */
348
+ getGovernedApis() {
349
+ // @ts-expect-error cast
350
+ return Far('governedAPIs', {});
351
+ },
352
+ getGovernedApiNames() {
353
+ return harden([]);
354
+ },
355
+ setOfferFilter: strings => zcf.setOfferFilter(strings),
356
+ },
357
+ machine: {
358
+ // TODO move this under governance #3924
359
+ /**
360
+ * @param {Issuer<'nat'>} collateralIssuer
361
+ * @param {Keyword} collateralKeyword
362
+ * @param {VaultManagerParamValues} initialParamValues
363
+ */
364
+ async addVaultType(
365
+ collateralIssuer,
366
+ collateralKeyword,
367
+ initialParamValues,
368
+ ) {
369
+ trace('addVaultType', collateralKeyword, initialParamValues);
370
+ mustMatch(collateralIssuer, M.remotable(), 'collateralIssuer');
371
+ assertKeywordName(collateralKeyword);
372
+ mustMatch(
373
+ initialParamValues,
374
+ vaultParamPattern,
375
+ 'initialParamValues',
376
+ );
377
+ await zcf.saveIssuer(collateralIssuer, collateralKeyword);
378
+ const collateralBrand = zcf.getBrandForIssuer(collateralIssuer);
379
+ // We create only one vault per collateralType.
380
+ !collateralManagers.has(collateralBrand) ||
381
+ Fail`Collateral brand ${q(collateralBrand)} has already been added`;
382
+
383
+ // zero-based index of the manager being made
384
+ const managerIndex = vaultManagers.length();
385
+ const managerId = `manager${managerIndex}`;
386
+ const managerStorageNode = await E(managersNode).makeChildNode(
387
+ managerId,
388
+ );
389
+
390
+ vaultParamManagers.addParamManager(
391
+ collateralBrand,
392
+ managerStorageNode,
393
+ initialParamValues,
394
+ );
395
+
396
+ const startTimeStamp = await E(timer).getCurrentTimestamp();
397
+
398
+ const collateralUnit = await unitAmount(collateralBrand);
399
+
400
+ const kit = await makeVaultManagerKit({
401
+ debtMint,
402
+ collateralBrand,
403
+ collateralUnit,
404
+ descriptionScope: managerId,
405
+ startTimeStamp,
406
+ storageNode: managerStorageNode,
407
+ });
408
+ vaultManagers.add(kit);
409
+ vaultManagers.length() - 1 === managerIndex ||
410
+ Fail`mismatch VaultManagerKit count`;
411
+ const { self: vm } = kit;
412
+ vm || Fail`no vault`;
413
+ collateralManagers.init(collateralBrand, managerIndex);
414
+ void writeMetrics();
415
+ return vm;
416
+ },
417
+ makeCollectFeesInvitation() {
418
+ return makeCollectFeesInvitation(
419
+ zcf,
420
+ rewardPoolSeat,
421
+ debtMint.getIssuerRecord().brand,
422
+ 'Minted',
423
+ );
424
+ },
425
+ // XXX accessors for tests
426
+ getRewardAllocation() {
427
+ return rewardPoolSeat.getCurrentAllocation();
428
+ },
429
+
430
+ makeLiquidationWaker() {
431
+ return makeWaker('liquidationWaker', _timestamp => {
432
+ allManagersDo(vm => vm.liquidateVaults(auctioneer));
433
+ });
434
+ },
435
+ makeReschedulerWaker() {
436
+ const { facets } = this;
437
+ return makeWaker('reschedulerWaker', () => {
438
+ void facets.helper.resetWakeupsForNextAuction();
439
+ });
440
+ },
441
+ makePriceLockWaker() {
442
+ return makeWaker('priceLockWaker', () => {
443
+ allManagersDo(vm => vm.lockOraclePrices());
444
+ });
445
+ },
446
+ },
447
+ public: {
448
+ /**
449
+ * @param {Brand} brandIn
450
+ */
451
+ getCollateralManager(brandIn) {
452
+ collateralManagers.has(brandIn) ||
453
+ Fail`Not a supported collateral type ${brandIn}`;
454
+ /** @type {VaultManager} */
455
+ return managerForCollateral(brandIn).getPublicFacet();
456
+ },
457
+ /**
458
+ * @deprecated get `collaterals` list from metrics
459
+ */
460
+ async getCollaterals() {
461
+ // should be collateralManagers.map((vm, brand) => ({
462
+ return harden(
463
+ Promise.all(
464
+ [...collateralManagers.entries()].map(
465
+ async ([brand, managerIndex]) => {
466
+ const vm = vaultManagers.get(managerIndex).self;
467
+ const priceQuote = await vm.getCollateralQuote();
468
+ return {
469
+ brand,
470
+ interestRate: vm.getGovernedParams().getInterestRate(),
471
+ liquidationMargin: vm
472
+ .getGovernedParams()
473
+ .getLiquidationMargin(),
474
+ stabilityFee: vm.getGovernedParams().getMintFee(),
475
+ marketPrice: makeRatioFromAmounts(
476
+ getAmountOut(priceQuote),
477
+ getAmountIn(priceQuote),
478
+ ),
479
+ };
480
+ },
481
+ ),
482
+ ),
483
+ );
484
+ },
485
+ /** @deprecated use getPublicTopics */
486
+ getMetrics() {
487
+ return metricsKit.subscriber;
488
+ },
489
+ getRunIssuer() {
490
+ return debtMint.getIssuerRecord().issuer;
491
+ },
492
+ /**
493
+ * @deprecated get from the CollateralManager directly
494
+ *
495
+ * subscription for the paramManager for a particular vaultManager
496
+ *
497
+ * @param {{ collateralBrand: Brand }} selector
498
+ */
499
+ getSubscription({ collateralBrand }) {
500
+ return vaultParamManagers.get(collateralBrand).getSubscription();
501
+ },
502
+ getPublicTopics() {
503
+ return topics;
504
+ },
505
+ /**
506
+ * subscription for the paramManager for the vaultFactory's electorate
507
+ */
508
+ getElectorateSubscription() {
509
+ return directorParamManager.getSubscription();
510
+ },
511
+ /**
512
+ * @param {{ collateralBrand: Brand }} selector
513
+ */
514
+ getGovernedParams({ collateralBrand }) {
515
+ // TODO use named getters of TypedParamManager
516
+ return vaultParamManagers.get(collateralBrand).getParams();
517
+ },
518
+ /**
519
+ * @param {string} name
520
+ */
521
+ getInvitationAmount(name) {
522
+ return directorParamManager.getInvitationAmount(name);
523
+ },
524
+ },
525
+ helper: {
526
+ resetWakeupsForNextAuction() {
527
+ const { facets } = this;
528
+
529
+ const priceLockWaker = facets.machine.makePriceLockWaker();
530
+ const liquidationWaker = facets.machine.makeLiquidationWaker();
531
+ const rescheduleWaker = facets.machine.makeReschedulerWaker();
532
+ return setWakeupsForNextAuction(
533
+ auctioneer,
534
+ timer,
535
+ priceLockWaker,
536
+ liquidationWaker,
537
+ rescheduleWaker,
538
+ );
539
+ },
540
+ /**
541
+ * Start non-durable processes (or restart if needed after vat restart)
542
+ */
543
+ async start() {
544
+ const { helper, machine } = this.facets;
545
+
546
+ await helper.resetWakeupsForNextAuction();
547
+ updateShortfallReporter().catch(err =>
548
+ console.error(
549
+ '🛠️ updateShortfallReporter failed during start(); repair by updating governance',
550
+ err,
551
+ ),
552
+ );
553
+ // independent of the other one which can be canceled
554
+ const rescheduleWaker = machine.makeReschedulerWaker();
555
+ void watchForGovernanceChange(auctioneer, timer, rescheduleWaker);
556
+ },
557
+ },
558
+ },
559
+ );
560
+ return makeVaultDirector;
555
561
  };
562
+ harden(prepareVaultDirector);
556
563
 
557
564
  /**
558
- * "Director" of the vault factory, overseeing "vault managers".
565
+ * Prepare the VaultDirector kind, get or make the singleton
559
566
  *
560
- * @param {ZCF<GovernanceTerms<{}> & {
561
- * ammPublicFacet: AutoswapPublicFacet,
562
- * liquidationInstall: Installation<import('./liquidateMinimum.js').start>,
563
- * loanTimingParams: {ChargingPeriod: ParamValueTyped<'nat'>, RecordingPeriod: ParamValueTyped<'nat'>},
564
- * reservePublicFacet: AssetReservePublicFacet,
565
- * timerService: TimerService,
566
- * priceAuthority: ERef<PriceAuthority>
567
- * }>} zcf
568
- * @param {import('@agoric/governance/src/contractGovernance/typedParamManager').TypedParamManager<import('./params.js').VaultDirectorParams>} directorParamManager
569
- * @param {ZCFMint<"nat">} debtMint
567
+ * @type {(...pvdArgs: Parameters<typeof prepareVaultDirector>) => ReturnType<ReturnType<typeof prepareVaultDirector>>}
570
568
  */
571
- const makeVaultDirector = defineDurableKindMulti(
572
- makeKindHandle('VaultDirector'),
573
- initState,
574
- behavior,
575
- { finish },
576
- );
577
-
578
- harden(makeVaultDirector);
579
- export { makeVaultDirector };
569
+ export const provideDirector = (...args) => {
570
+ const makeVaultDirector = prepareVaultDirector(...args);
571
+
572
+ const [baggage] = args;
573
+
574
+ return provide(baggage, 'director', makeVaultDirector);
575
+ };
576
+ harden(provideDirector);