@agoric/inter-protocol 0.13.2-dev-55d06de.0 → 0.13.2-dev-097dca8.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.
- package/bundles/bundle-amm-meta.js +128 -128
- package/bundles/bundle-amm.js +1 -1
- package/bundles/bundle-econCommitteeCharter-meta.js +74 -74
- package/bundles/bundle-econCommitteeCharter.js +1 -1
- package/bundles/bundle-feeDistributor-meta.js +54 -54
- package/bundles/bundle-feeDistributor.js +1 -1
- package/bundles/bundle-interchainPool-meta.js +104 -104
- package/bundles/bundle-interchainPool.js +1 -1
- package/bundles/bundle-liquidateIncrementally-meta.js +68 -68
- package/bundles/bundle-liquidateIncrementally.js +1 -1
- package/bundles/bundle-liquidateMinimum-meta.js +68 -68
- package/bundles/bundle-liquidateMinimum.js +1 -1
- package/bundles/bundle-priceAggregatorChainlink-meta.js +73 -73
- package/bundles/bundle-priceAggregatorChainlink.js +1 -1
- package/bundles/bundle-psm-meta.js +107 -107
- package/bundles/bundle-psm.js +1 -1
- package/bundles/bundle-reserve-meta.js +105 -105
- package/bundles/bundle-reserve.js +1 -1
- package/bundles/bundle-scaledPriceAuthority-meta.js +80 -80
- package/bundles/bundle-scaledPriceAuthority.js +1 -1
- package/bundles/bundle-stakeFactory-meta.js +114 -114
- package/bundles/bundle-stakeFactory.js +1 -1
- package/bundles/bundle-vaultFactory-meta.js +132 -132
- package/bundles/bundle-vaultFactory.js +1 -1
- package/package.json +14 -14
- package/src/contractSupport.js +7 -0
- package/src/vaultFactory/vault.js +48 -83
- package/src/vaultFactory/vaultDirector.js +427 -528
- package/src/vaultFactory/vaultFactory.js +7 -3
- package/src/vaultFactory/vaultHolder.js +3 -3
- package/src/vaultFactory/vaultKit.js +9 -5
- package/src/vaultFactory/vaultManager.js +132 -256
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
import {
|
|
25
25
|
defineDurableExoClassKit,
|
|
26
26
|
makeKindHandle,
|
|
27
|
-
|
|
27
|
+
provideDurableMapStore,
|
|
28
28
|
} from '@agoric/vat-data';
|
|
29
29
|
import { assertKeywordName } from '@agoric/zoe/src/cleanProposal.js';
|
|
30
30
|
import { unitAmount } from '@agoric/zoe/src/contractSupport/priceQuote.js';
|
|
@@ -37,34 +37,10 @@ import {
|
|
|
37
37
|
vaultParamPattern,
|
|
38
38
|
} from './params.js';
|
|
39
39
|
import { prepareVaultManagerKit } from './vaultManager.js';
|
|
40
|
-
import { provideChildBaggage } from '../contractSupport.js';
|
|
40
|
+
import { provideChildBaggage, provideEmptySeat } from '../contractSupport.js';
|
|
41
41
|
|
|
42
42
|
const { details: X, quote: q, Fail } = assert;
|
|
43
43
|
|
|
44
|
-
/** @typedef {{
|
|
45
|
-
* debtMint: ZCFMint<'nat'>,
|
|
46
|
-
* directorParamManager: import('@agoric/governance/src/contractGovernance/typedParamManager').TypedParamManager<import('./params.js').VaultDirectorParams>,
|
|
47
|
-
* managerBaggages: import('../contractSupport.js').ChildBaggageManager,
|
|
48
|
-
* marshaller: ERef<Marshaller>,
|
|
49
|
-
* shortfallReporter: import('../reserve/assetReserve.js').ShortfallReporter,
|
|
50
|
-
* storedMetricsSubscriber: StoredSubscriber<MetricsNotification>,
|
|
51
|
-
* storageNode: ERef<StorageNode>,
|
|
52
|
-
* vaultParamManagers: MapStore<Brand, import('./params.js').VaultParamManager>,
|
|
53
|
-
* zcf: import('./vaultFactory.js').VaultFactoryZCF,
|
|
54
|
-
* }} Ephemera
|
|
55
|
-
*/
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Ephemera is the state we cannot (or merely need not) keep durably. For
|
|
59
|
-
* vaultDirector we can keep it in module scope because there is (exactly) one
|
|
60
|
-
* vaultDirector per vaultFactory contract and (exactly) one contract per vat.
|
|
61
|
-
*
|
|
62
|
-
* @type {Ephemera}
|
|
63
|
-
*/
|
|
64
|
-
// @ts-expect-error not actually full until after initState
|
|
65
|
-
// UNTIL resolution to https://github.com/Agoric/agoric-sdk/issues/5759
|
|
66
|
-
const ephemera = {};
|
|
67
|
-
|
|
68
44
|
/**
|
|
69
45
|
* @typedef {{
|
|
70
46
|
* collaterals: Brand[],
|
|
@@ -72,12 +48,6 @@ const ephemera = {};
|
|
|
72
48
|
* }} MetricsNotification
|
|
73
49
|
*
|
|
74
50
|
* @typedef {Readonly<{
|
|
75
|
-
* collateralTypes: MapStore<Brand,VaultManager>,
|
|
76
|
-
* metricsPublisher: Publisher<MetricsNotification>
|
|
77
|
-
* metricsSubscriber: Subscriber<MetricsNotification>
|
|
78
|
-
* mintSeat: ZCFSeat,
|
|
79
|
-
* rewardPoolSeat: ZCFSeat,
|
|
80
|
-
* shortfallInvitation: Invitation,
|
|
81
51
|
* }>} ImmutableState
|
|
82
52
|
*
|
|
83
53
|
* @typedef {{
|
|
@@ -99,94 +69,40 @@ const ephemera = {};
|
|
|
99
69
|
*/
|
|
100
70
|
// TODO find a way to type 'finish' with the context (state and facets)
|
|
101
71
|
|
|
102
|
-
|
|
103
|
-
* @param {ERef<ZoeService>} zoe
|
|
104
|
-
* @param {Ephemera['directorParamManager']} paramMgr
|
|
105
|
-
* @param {import('../reserve/assetReserve.js').ShortfallReporter} [oldShortfallReporter]
|
|
106
|
-
* @param {ERef<Invitation>} [oldInvitation]
|
|
107
|
-
* @returns {Promise<{
|
|
108
|
-
* shortfallInvitation: ERef<Invitation>,
|
|
109
|
-
* shortfallReporter: import('../reserve/assetReserve.js').ShortfallReporter,
|
|
110
|
-
* }>}
|
|
111
|
-
*/
|
|
112
|
-
const updateShortfallReporter = async (
|
|
113
|
-
zoe,
|
|
114
|
-
paramMgr,
|
|
115
|
-
oldShortfallReporter,
|
|
116
|
-
oldInvitation,
|
|
117
|
-
) => {
|
|
118
|
-
const newInvitation = paramMgr.getInternalParamValue(
|
|
119
|
-
SHORTFALL_INVITATION_KEY,
|
|
120
|
-
);
|
|
121
|
-
|
|
122
|
-
if (newInvitation !== oldInvitation) {
|
|
123
|
-
return {
|
|
124
|
-
// @ts-expect-error cast
|
|
125
|
-
shortfallReporter: E(E(zoe).offer(newInvitation)).getOfferResult(),
|
|
126
|
-
shortfallInvitation: newInvitation,
|
|
127
|
-
};
|
|
128
|
-
} else {
|
|
129
|
-
assert(
|
|
130
|
-
oldShortfallReporter,
|
|
131
|
-
'updateShortFallReported called with repeat invitation and no oldShortfallReporter',
|
|
132
|
-
);
|
|
133
|
-
return {
|
|
134
|
-
shortfallReporter: oldShortfallReporter,
|
|
135
|
-
shortfallInvitation: oldInvitation,
|
|
136
|
-
};
|
|
137
|
-
}
|
|
138
|
-
};
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* @param {Pick<State, 'collateralTypes' | 'rewardPoolSeat'>} state
|
|
142
|
-
* @returns {MetricsNotification}
|
|
143
|
-
*/
|
|
144
|
-
const metricsOf = state => {
|
|
145
|
-
return harden({
|
|
146
|
-
collaterals: Array.from(state.collateralTypes.keys()),
|
|
147
|
-
rewardPoolAllocation: state.rewardPoolSeat.getCurrentAllocation(),
|
|
148
|
-
});
|
|
149
|
-
};
|
|
150
|
-
|
|
151
|
-
// UNTIL https://github.com/Agoric/agoric-sdk/issues/6791
|
|
152
|
-
const baggage = makeScalarBigMapStore('Vault Director baggage', {
|
|
153
|
-
durable: true,
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
const makeVaultDirectorMetricsPublishKit = prepareDurablePublishKit(
|
|
157
|
-
baggage,
|
|
158
|
-
'Vault Director metrics',
|
|
159
|
-
);
|
|
72
|
+
const shortfallInvitationKey = 'shortfallInvitation';
|
|
160
73
|
|
|
161
74
|
/**
|
|
162
|
-
* @param {
|
|
163
|
-
* @param {
|
|
164
|
-
* @param {
|
|
75
|
+
* @param {import('@agoric/ertp').Baggage} baggage
|
|
76
|
+
* @param {import('./vaultFactory.js').VaultFactoryZCF} zcf
|
|
77
|
+
* @param {import('@agoric/governance/src/contractGovernance/typedParamManager').TypedParamManager<import('./params.js').VaultDirectorParams>} directorParamManager
|
|
78
|
+
* @param {ZCFMint<"nat">} debtMint
|
|
165
79
|
* @param {ERef<StorageNode>} storageNode
|
|
166
80
|
* @param {ERef<Marshaller>} marshaller
|
|
167
|
-
* @returns {State}
|
|
168
81
|
*/
|
|
169
|
-
const
|
|
82
|
+
export const prepareVaultDirector = (
|
|
83
|
+
baggage,
|
|
170
84
|
zcf,
|
|
171
85
|
directorParamManager,
|
|
172
86
|
debtMint,
|
|
173
87
|
storageNode,
|
|
174
88
|
marshaller,
|
|
175
89
|
) => {
|
|
90
|
+
const makeVaultDirectorPublishKit = prepareDurablePublishKit(
|
|
91
|
+
baggage,
|
|
92
|
+
'Vault Director publish kit',
|
|
93
|
+
);
|
|
176
94
|
/** For temporary staging of newly minted tokens */
|
|
177
|
-
const
|
|
178
|
-
const
|
|
95
|
+
const mintSeat = provideEmptySeat(zcf, baggage, 'mintSeat');
|
|
96
|
+
const rewardPoolSeat = provideEmptySeat(zcf, baggage, 'rewardPoolSeat');
|
|
179
97
|
|
|
180
|
-
const collateralTypes =
|
|
181
|
-
durable: true,
|
|
182
|
-
});
|
|
98
|
+
const collateralTypes = provideDurableMapStore(baggage, 'collateralTypes');
|
|
183
99
|
|
|
184
100
|
// Non-durable map because param managers aren't durable.
|
|
185
101
|
// In the event they're needed they can be reconstructed from contract terms and off-chain data.
|
|
186
102
|
const vaultParamManagers = makeScalarMapStore('vaultParamManagers');
|
|
187
103
|
|
|
188
104
|
const { publisher: metricsPublisher, subscriber: metricsSubscriber } =
|
|
189
|
-
|
|
105
|
+
makeVaultDirectorPublishKit();
|
|
190
106
|
|
|
191
107
|
const storedMetricsSubscriber = makeStoredSubscriber(
|
|
192
108
|
metricsSubscriber,
|
|
@@ -196,450 +112,433 @@ const initState = (
|
|
|
196
112
|
|
|
197
113
|
const managerBaggages = provideChildBaggage(baggage, 'Vault Manager baggage');
|
|
198
114
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
directorParamManager,
|
|
202
|
-
managerBaggages,
|
|
203
|
-
marshaller,
|
|
204
|
-
storedMetricsSubscriber,
|
|
205
|
-
storageNode,
|
|
206
|
-
vaultParamManagers,
|
|
207
|
-
zcf,
|
|
208
|
-
});
|
|
115
|
+
/** @type {import('../reserve/assetReserve.js').ShortfallReporter} */
|
|
116
|
+
let shortfallReporter;
|
|
209
117
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
// @ts-expect-error defined in finish()
|
|
218
|
-
shortfallInvitation: undefined,
|
|
118
|
+
/**
|
|
119
|
+
* @returns {State}
|
|
120
|
+
*/
|
|
121
|
+
const initState = () => {
|
|
122
|
+
return {
|
|
123
|
+
managerCounter: 0,
|
|
124
|
+
};
|
|
219
125
|
};
|
|
220
|
-
};
|
|
221
126
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
const getLiquidationConfig = directorParamManager => ({
|
|
226
|
-
install: directorParamManager.getLiquidationInstall(),
|
|
227
|
-
terms: directorParamManager.getLiquidationTerms(),
|
|
228
|
-
});
|
|
229
|
-
|
|
230
|
-
/**
|
|
231
|
-
*
|
|
232
|
-
* @param {Ephemera['directorParamManager']} govParams
|
|
233
|
-
* @param {VaultManager} vaultManager
|
|
234
|
-
* @param {Installation<unknown>} oldInstall
|
|
235
|
-
* @param {unknown} oldTerms
|
|
236
|
-
*/
|
|
237
|
-
const watchGovernance = (govParams, vaultManager, oldInstall, oldTerms) => {
|
|
238
|
-
const subscription = govParams.getSubscription();
|
|
239
|
-
void observeIteration(subscription, {
|
|
240
|
-
updateState(_paramUpdate) {
|
|
241
|
-
const { install, terms } = getLiquidationConfig(govParams);
|
|
242
|
-
if (install === oldInstall && keyEQ(terms, oldTerms)) {
|
|
243
|
-
return;
|
|
244
|
-
}
|
|
245
|
-
oldInstall = install;
|
|
246
|
-
oldTerms = terms;
|
|
247
|
-
vaultManager
|
|
248
|
-
.setupLiquidator(install, terms)
|
|
249
|
-
.catch(e => console.error('Failed to setup liquidator', e));
|
|
250
|
-
},
|
|
127
|
+
const getLiquidationConfig = () => ({
|
|
128
|
+
install: directorParamManager.getLiquidationInstall(),
|
|
129
|
+
terms: directorParamManager.getLiquidationTerms(),
|
|
251
130
|
});
|
|
252
|
-
};
|
|
253
131
|
|
|
254
|
-
/**
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
state.shortfallInvitation = shortfallInvitation;
|
|
264
|
-
};
|
|
132
|
+
/**
|
|
133
|
+
* @returns {MetricsNotification}
|
|
134
|
+
*/
|
|
135
|
+
const sampleMetrics = () => {
|
|
136
|
+
return harden({
|
|
137
|
+
collaterals: Array.from(collateralTypes.keys()),
|
|
138
|
+
rewardPoolAllocation: rewardPoolSeat.getCurrentAllocation(),
|
|
139
|
+
});
|
|
140
|
+
};
|
|
265
141
|
|
|
266
|
-
/**
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
getInvitation: M.call(M.string()).returns(M.promise()),
|
|
286
|
-
getLimitedCreatorFacet: M.call().returns(M.remotable()),
|
|
287
|
-
getGovernedApis: M.call().returns(M.record()),
|
|
288
|
-
getGovernedApiNames: M.call().returns(M.record()),
|
|
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
|
-
getContractGovernor: M.call().returns(M.remotable()),
|
|
296
|
-
updateMetrics: M.call().returns(),
|
|
297
|
-
getRewardAllocation: M.call().returns({ Minted: AmountShape }),
|
|
298
|
-
}),
|
|
299
|
-
public: M.interface('public', {
|
|
300
|
-
getCollateralManager: M.call(BrandShape).returns(M.remotable()),
|
|
301
|
-
getCollaterals: M.call().returns(M.promise()),
|
|
302
|
-
getMetrics: M.call().returns(SubscriberShape),
|
|
303
|
-
makeVaultInvitation: M.call().returns(M.promise()),
|
|
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
|
-
getContractGovernor: M.call().returns(M.remotable()),
|
|
313
|
-
getInvitationAmount: M.call(M.string()).returns(AmountShape),
|
|
314
|
-
}),
|
|
315
|
-
},
|
|
316
|
-
initState,
|
|
317
|
-
{
|
|
318
|
-
creator: {
|
|
319
|
-
getParamMgrRetriever: () =>
|
|
320
|
-
Far('paramManagerRetriever', {
|
|
321
|
-
/** @param {VaultFactoryParamPath} paramPath */
|
|
322
|
-
get: paramPath => {
|
|
323
|
-
if (paramPath.key === 'governedParams') {
|
|
324
|
-
return ephemera.directorParamManager;
|
|
325
|
-
} else if (paramPath.key.collateralBrand) {
|
|
326
|
-
return ephemera.vaultParamManagers.get(
|
|
327
|
-
paramPath.key.collateralBrand,
|
|
328
|
-
);
|
|
329
|
-
} else {
|
|
330
|
-
assert.fail('Unsupported paramPath');
|
|
331
|
-
}
|
|
332
|
-
},
|
|
333
|
-
}),
|
|
334
|
-
/**
|
|
335
|
-
* @param {string} name
|
|
336
|
-
*/
|
|
337
|
-
getInvitation(name) {
|
|
338
|
-
return ephemera.directorParamManager.getInternalParamValue(name);
|
|
339
|
-
},
|
|
340
|
-
getLimitedCreatorFacet() {
|
|
341
|
-
return this.facets.machine;
|
|
142
|
+
/**
|
|
143
|
+
*
|
|
144
|
+
* @param {VaultManager} vaultManager
|
|
145
|
+
* @param {Installation<unknown>} oldInstall
|
|
146
|
+
* @param {unknown} oldTerms
|
|
147
|
+
*/
|
|
148
|
+
const watchGovernance = (vaultManager, oldInstall, oldTerms) => {
|
|
149
|
+
const subscription = directorParamManager.getSubscription();
|
|
150
|
+
void observeIteration(subscription, {
|
|
151
|
+
updateState(_paramUpdate) {
|
|
152
|
+
const { install, terms } = getLiquidationConfig();
|
|
153
|
+
if (install === oldInstall && keyEQ(terms, oldTerms)) {
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
oldInstall = install;
|
|
157
|
+
oldTerms = terms;
|
|
158
|
+
vaultManager
|
|
159
|
+
.setupLiquidator(install, terms)
|
|
160
|
+
.catch(e => console.error('Failed to setup liquidator', e));
|
|
342
161
|
},
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
},
|
|
346
|
-
getGovernedApiNames() {
|
|
347
|
-
return harden({});
|
|
348
|
-
},
|
|
349
|
-
},
|
|
350
|
-
machine: {
|
|
351
|
-
// TODO move this under governance #3924
|
|
352
|
-
/**
|
|
353
|
-
* @param {Issuer<'nat'>} collateralIssuer
|
|
354
|
-
* @param {Keyword} collateralKeyword
|
|
355
|
-
* @param {VaultManagerParamValues} initialParamValues
|
|
356
|
-
*/
|
|
357
|
-
async addVaultType(
|
|
358
|
-
collateralIssuer,
|
|
359
|
-
collateralKeyword,
|
|
360
|
-
initialParamValues,
|
|
361
|
-
) {
|
|
362
|
-
const { state, facets } = this;
|
|
363
|
-
const {
|
|
364
|
-
debtMint,
|
|
365
|
-
vaultParamManagers,
|
|
366
|
-
directorParamManager,
|
|
367
|
-
marshaller,
|
|
368
|
-
storageNode,
|
|
369
|
-
zcf,
|
|
370
|
-
} = ephemera;
|
|
371
|
-
const { collateralTypes, mintSeat, rewardPoolSeat } = state;
|
|
372
|
-
mustMatch(collateralIssuer, M.remotable(), 'collateralIssuer');
|
|
373
|
-
assertKeywordName(collateralKeyword);
|
|
374
|
-
mustMatch(initialParamValues, vaultParamPattern, 'initialParamValues');
|
|
375
|
-
await zcf.saveIssuer(collateralIssuer, collateralKeyword);
|
|
376
|
-
const collateralBrand = zcf.getBrandForIssuer(collateralIssuer);
|
|
377
|
-
// We create only one vault per collateralType.
|
|
378
|
-
!collateralTypes.has(collateralBrand) ||
|
|
379
|
-
Fail`Collateral brand ${q(collateralBrand)} has already been added`;
|
|
380
|
-
|
|
381
|
-
const managerStorageNode =
|
|
382
|
-
storageNode &&
|
|
383
|
-
E(storageNode).makeChildNode(`manager${state.managerCounter}`);
|
|
384
|
-
state.managerCounter += 1;
|
|
385
|
-
|
|
386
|
-
/** a powerful object; can modify parameters */
|
|
387
|
-
const vaultParamManager = makeVaultParamManager(
|
|
388
|
-
makeStoredPublisherKit(managerStorageNode, marshaller, 'governance'),
|
|
389
|
-
initialParamValues,
|
|
390
|
-
);
|
|
391
|
-
vaultParamManagers.init(collateralBrand, vaultParamManager);
|
|
162
|
+
});
|
|
163
|
+
};
|
|
392
164
|
|
|
393
|
-
|
|
394
|
-
|
|
165
|
+
const updateShortfallReporter = async () => {
|
|
166
|
+
const oldInvitation = baggage.has(shortfallInvitationKey)
|
|
167
|
+
? baggage.get(shortfallInvitationKey)
|
|
168
|
+
: undefined;
|
|
169
|
+
const newInvitation = directorParamManager.getInternalParamValue(
|
|
170
|
+
SHORTFALL_INVITATION_KEY,
|
|
171
|
+
);
|
|
395
172
|
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
console.error('mintAndReallocate caught', e);
|
|
413
|
-
mintSeat.clear();
|
|
414
|
-
rewardPoolSeat.clear();
|
|
415
|
-
// Make best efforts to burn the newly minted tokens, for hygiene.
|
|
416
|
-
// That only relies on the internal mint, so it cannot fail without
|
|
417
|
-
// there being much larger problems. There's no risk of tokens being
|
|
418
|
-
// stolen here because the staging for them was already cleared.
|
|
419
|
-
debtMint.burnLosses(harden({ Minted: toMint }), mintSeat);
|
|
420
|
-
throw e;
|
|
421
|
-
} finally {
|
|
422
|
-
// Note that if this assertion may fail because of an error in the
|
|
423
|
-
// try{} block, but that error won't be thrown because this executes
|
|
424
|
-
// before the catch that rethrows it.
|
|
425
|
-
assert(
|
|
426
|
-
Object.values(mintSeat.getCurrentAllocation()).every(a =>
|
|
427
|
-
AmountMath.isEmpty(a),
|
|
428
|
-
),
|
|
429
|
-
X`Stage should be empty of Minted`,
|
|
430
|
-
);
|
|
431
|
-
}
|
|
432
|
-
facets.machine.updateMetrics();
|
|
433
|
-
};
|
|
173
|
+
if (newInvitation === oldInvitation) {
|
|
174
|
+
shortfallReporter ||
|
|
175
|
+
'updateShortFallReported called with repeat invitation and no prior shortfallReporter';
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Update the values
|
|
180
|
+
const zoe = zcf.getZoeService();
|
|
181
|
+
// @ts-expect-error cast
|
|
182
|
+
shortfallReporter = E(E(zoe).offer(newInvitation)).getOfferResult();
|
|
183
|
+
if (oldInvitation === undefined) {
|
|
184
|
+
baggage.init(shortfallInvitationKey, newInvitation);
|
|
185
|
+
} else {
|
|
186
|
+
baggage.set(shortfallInvitationKey, newInvitation);
|
|
187
|
+
}
|
|
188
|
+
};
|
|
434
189
|
|
|
190
|
+
const finish = async () => {
|
|
191
|
+
await updateShortfallReporter();
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* "Director" of the vault factory, overseeing "vault managers".
|
|
196
|
+
*
|
|
197
|
+
* @param {import('./vaultFactory.js').VaultFactoryZCF} zcf
|
|
198
|
+
* @param {import('@agoric/governance/src/contractGovernance/typedParamManager').TypedParamManager<import('./params.js').VaultDirectorParams>} directorParamManager
|
|
199
|
+
* @param {ZCFMint<"nat">} debtMint
|
|
200
|
+
*/
|
|
201
|
+
const makeVaultDirector = defineDurableExoClassKit(
|
|
202
|
+
makeKindHandle('VaultDirector'),
|
|
203
|
+
{
|
|
204
|
+
creator: M.interface('creator', {
|
|
205
|
+
getParamMgrRetriever: M.call().returns(M.remotable()),
|
|
206
|
+
getInvitation: M.call(M.string()).returns(M.promise()),
|
|
207
|
+
getLimitedCreatorFacet: M.call().returns(M.remotable()),
|
|
208
|
+
getGovernedApis: M.call().returns(M.record()),
|
|
209
|
+
getGovernedApiNames: M.call().returns(M.record()),
|
|
210
|
+
}),
|
|
211
|
+
machine: M.interface('machine', {
|
|
212
|
+
addVaultType: M.call(IssuerShape, M.string(), M.record()).returns(
|
|
213
|
+
M.promise(),
|
|
214
|
+
),
|
|
215
|
+
makeCollectFeesInvitation: M.call().returns(M.promise()),
|
|
216
|
+
getContractGovernor: M.call().returns(M.remotable()),
|
|
217
|
+
updateMetrics: M.call().returns(),
|
|
218
|
+
getRewardAllocation: M.call().returns({ Minted: AmountShape }),
|
|
219
|
+
}),
|
|
220
|
+
public: M.interface('public', {
|
|
221
|
+
getCollateralManager: M.call(BrandShape).returns(M.remotable()),
|
|
222
|
+
getCollaterals: M.call().returns(M.promise()),
|
|
223
|
+
getMetrics: M.call().returns(SubscriberShape),
|
|
224
|
+
makeVaultInvitation: M.call().returns(M.promise()),
|
|
225
|
+
getRunIssuer: M.call().returns(IssuerShape),
|
|
226
|
+
getSubscription: M.call({ collateralBrand: BrandShape }).returns(
|
|
227
|
+
SubscriberShape,
|
|
228
|
+
),
|
|
229
|
+
getElectorateSubscription: M.call().returns(SubscriberShape),
|
|
230
|
+
getGovernedParams: M.call({ collateralBrand: BrandShape }).returns(
|
|
231
|
+
M.record(),
|
|
232
|
+
),
|
|
233
|
+
getContractGovernor: M.call().returns(M.remotable()),
|
|
234
|
+
getInvitationAmount: M.call(M.string()).returns(AmountShape),
|
|
235
|
+
}),
|
|
236
|
+
},
|
|
237
|
+
initState,
|
|
238
|
+
{
|
|
239
|
+
creator: {
|
|
240
|
+
getParamMgrRetriever: () =>
|
|
241
|
+
Far('paramManagerRetriever', {
|
|
242
|
+
/** @param {VaultFactoryParamPath} paramPath */
|
|
243
|
+
get: paramPath => {
|
|
244
|
+
if (paramPath.key === 'governedParams') {
|
|
245
|
+
return directorParamManager;
|
|
246
|
+
} else if (paramPath.key.collateralBrand) {
|
|
247
|
+
return vaultParamManagers.get(paramPath.key.collateralBrand);
|
|
248
|
+
} else {
|
|
249
|
+
assert.fail('Unsupported paramPath');
|
|
250
|
+
}
|
|
251
|
+
},
|
|
252
|
+
}),
|
|
435
253
|
/**
|
|
436
|
-
* @param {
|
|
437
|
-
* @param {ZCFSeat} seat
|
|
254
|
+
* @param {string} name
|
|
438
255
|
*/
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
getDebtLimit: vaultParamManager.readonly().getDebtLimit,
|
|
452
|
-
getChargingPeriod: () =>
|
|
453
|
-
loanTimingParams[CHARGING_PERIOD_KEY].value,
|
|
454
|
-
getRecordingPeriod: () =>
|
|
455
|
-
loanTimingParams[RECORDING_PERIOD_KEY].value,
|
|
456
|
-
}),
|
|
457
|
-
mintAndReallocate,
|
|
458
|
-
getShortfallReporter: async () => {
|
|
459
|
-
const reporterKit = await updateShortfallReporter(
|
|
460
|
-
zcf.getZoeService(),
|
|
461
|
-
directorParamManager,
|
|
462
|
-
ephemera.shortfallReporter,
|
|
463
|
-
state.shortfallInvitation,
|
|
464
|
-
);
|
|
465
|
-
return reporterKit.shortfallReporter;
|
|
466
|
-
},
|
|
467
|
-
burnDebt,
|
|
468
|
-
});
|
|
469
|
-
|
|
470
|
-
const { managerBaggages } = ephemera;
|
|
471
|
-
// alleged okay because used only as a diagnostic tag
|
|
472
|
-
const brandName = await E(collateralBrand).getAllegedName();
|
|
473
|
-
const collateralUnit = await unitAmount(collateralBrand);
|
|
474
|
-
|
|
475
|
-
const makeVaultManager = managerBaggages.addChild(
|
|
476
|
-
brandName,
|
|
477
|
-
prepareVaultManagerKit,
|
|
478
|
-
zcf,
|
|
479
|
-
debtMint,
|
|
480
|
-
collateralBrand,
|
|
481
|
-
collateralUnit,
|
|
482
|
-
factoryPowers,
|
|
483
|
-
startTimeStamp,
|
|
484
|
-
managerStorageNode,
|
|
485
|
-
marshaller,
|
|
486
|
-
);
|
|
487
|
-
|
|
488
|
-
const { self: vm } = makeVaultManager();
|
|
489
|
-
collateralTypes.init(collateralBrand, vm);
|
|
490
|
-
const { install, terms } = getLiquidationConfig(directorParamManager);
|
|
491
|
-
await vm.setupLiquidator(install, terms);
|
|
492
|
-
watchGovernance(directorParamManager, vm, install, terms);
|
|
493
|
-
facets.machine.updateMetrics();
|
|
494
|
-
return vm;
|
|
495
|
-
},
|
|
496
|
-
makeCollectFeesInvitation() {
|
|
497
|
-
const { state } = this;
|
|
498
|
-
const { debtMint, zcf } = ephemera;
|
|
499
|
-
const { rewardPoolSeat } = state;
|
|
500
|
-
return makeMakeCollectFeesInvitation(
|
|
501
|
-
zcf,
|
|
502
|
-
rewardPoolSeat,
|
|
503
|
-
debtMint.getIssuerRecord().brand,
|
|
504
|
-
'Minted',
|
|
505
|
-
).makeCollectFeesInvitation();
|
|
506
|
-
},
|
|
507
|
-
getContractGovernor() {
|
|
508
|
-
return ephemera.zcf.getTerms().electionManager;
|
|
509
|
-
},
|
|
510
|
-
updateMetrics() {
|
|
511
|
-
const { state } = this;
|
|
512
|
-
return state.metricsPublisher.publish(metricsOf(harden(state)));
|
|
513
|
-
},
|
|
514
|
-
// XXX accessors for tests
|
|
515
|
-
getRewardAllocation() {
|
|
516
|
-
return this.state.rewardPoolSeat.getCurrentAllocation();
|
|
256
|
+
getInvitation(name) {
|
|
257
|
+
return directorParamManager.getInternalParamValue(name);
|
|
258
|
+
},
|
|
259
|
+
getLimitedCreatorFacet() {
|
|
260
|
+
return this.facets.machine;
|
|
261
|
+
},
|
|
262
|
+
getGovernedApis() {
|
|
263
|
+
return harden({});
|
|
264
|
+
},
|
|
265
|
+
getGovernedApiNames() {
|
|
266
|
+
return harden({});
|
|
267
|
+
},
|
|
517
268
|
},
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
269
|
+
machine: {
|
|
270
|
+
// TODO move this under governance #3924
|
|
271
|
+
/**
|
|
272
|
+
* @param {Issuer<'nat'>} collateralIssuer
|
|
273
|
+
* @param {Keyword} collateralKeyword
|
|
274
|
+
* @param {VaultManagerParamValues} initialParamValues
|
|
275
|
+
*/
|
|
276
|
+
async addVaultType(
|
|
277
|
+
collateralIssuer,
|
|
278
|
+
collateralKeyword,
|
|
279
|
+
initialParamValues,
|
|
280
|
+
) {
|
|
281
|
+
const { state, facets } = this;
|
|
282
|
+
mustMatch(collateralIssuer, M.remotable(), 'collateralIssuer');
|
|
283
|
+
assertKeywordName(collateralKeyword);
|
|
284
|
+
mustMatch(
|
|
285
|
+
initialParamValues,
|
|
286
|
+
vaultParamPattern,
|
|
287
|
+
'initialParamValues',
|
|
288
|
+
);
|
|
289
|
+
await zcf.saveIssuer(collateralIssuer, collateralKeyword);
|
|
290
|
+
const collateralBrand = zcf.getBrandForIssuer(collateralIssuer);
|
|
291
|
+
// We create only one vault per collateralType.
|
|
292
|
+
!collateralTypes.has(collateralBrand) ||
|
|
293
|
+
Fail`Collateral brand ${q(collateralBrand)} has already been added`;
|
|
294
|
+
|
|
295
|
+
const managerStorageNode =
|
|
296
|
+
storageNode &&
|
|
297
|
+
E(storageNode).makeChildNode(`manager${state.managerCounter}`);
|
|
298
|
+
state.managerCounter += 1;
|
|
299
|
+
|
|
300
|
+
/** a powerful object; can modify parameters */
|
|
301
|
+
const vaultParamManager = makeVaultParamManager(
|
|
302
|
+
makeStoredPublisherKit(
|
|
303
|
+
managerStorageNode,
|
|
304
|
+
marshaller,
|
|
305
|
+
'governance',
|
|
306
|
+
),
|
|
307
|
+
initialParamValues,
|
|
308
|
+
);
|
|
309
|
+
vaultParamManagers.init(collateralBrand, vaultParamManager);
|
|
310
|
+
|
|
311
|
+
const { timerService } = zcf.getTerms();
|
|
312
|
+
const startTimeStamp = await E(timerService).getCurrentTimestamp();
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* We provide an easy way for the vaultManager to add rewards to
|
|
316
|
+
* the rewardPoolSeat, without directly exposing the rewardPoolSeat to them.
|
|
317
|
+
*
|
|
318
|
+
* @type {MintAndReallocate}
|
|
319
|
+
*/
|
|
320
|
+
const mintAndReallocate = (toMint, fee, seat, ...otherSeats) => {
|
|
321
|
+
const kept = AmountMath.subtract(toMint, fee);
|
|
322
|
+
debtMint.mintGains(harden({ Minted: toMint }), mintSeat);
|
|
323
|
+
try {
|
|
324
|
+
rewardPoolSeat.incrementBy(
|
|
325
|
+
mintSeat.decrementBy(harden({ Minted: fee })),
|
|
326
|
+
);
|
|
327
|
+
seat.incrementBy(mintSeat.decrementBy(harden({ Minted: kept })));
|
|
328
|
+
zcf.reallocate(rewardPoolSeat, mintSeat, seat, ...otherSeats);
|
|
329
|
+
} catch (e) {
|
|
330
|
+
console.error('mintAndReallocate caught', e);
|
|
331
|
+
mintSeat.clear();
|
|
332
|
+
rewardPoolSeat.clear();
|
|
333
|
+
// Make best efforts to burn the newly minted tokens, for hygiene.
|
|
334
|
+
// That only relies on the internal mint, so it cannot fail without
|
|
335
|
+
// there being much larger problems. There's no risk of tokens being
|
|
336
|
+
// stolen here because the staging for them was already cleared.
|
|
337
|
+
debtMint.burnLosses(harden({ Minted: toMint }), mintSeat);
|
|
338
|
+
throw e;
|
|
339
|
+
} finally {
|
|
340
|
+
// Note that if this assertion may fail because of an error in the
|
|
341
|
+
// try{} block, but that error won't be thrown because this executes
|
|
342
|
+
// before the catch that rethrows it.
|
|
343
|
+
assert(
|
|
344
|
+
Object.values(mintSeat.getCurrentAllocation()).every(a =>
|
|
345
|
+
AmountMath.isEmpty(a),
|
|
551
346
|
),
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
347
|
+
X`Stage should be empty of Minted`,
|
|
348
|
+
);
|
|
349
|
+
}
|
|
350
|
+
facets.machine.updateMetrics();
|
|
351
|
+
};
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* @param {Amount<'nat'>} toBurn
|
|
355
|
+
* @param {ZCFSeat} seat
|
|
356
|
+
*/
|
|
357
|
+
const burnDebt = (toBurn, seat) => {
|
|
358
|
+
debtMint.burnLosses(harden({ Minted: toBurn }), seat);
|
|
359
|
+
};
|
|
360
|
+
|
|
361
|
+
const { loanTimingParams } = zcf.getTerms();
|
|
362
|
+
|
|
363
|
+
const factoryPowers = Far('vault factory powers', {
|
|
364
|
+
getGovernedParams: () =>
|
|
365
|
+
Far('vault manager param manager', {
|
|
366
|
+
...vaultParamManager.readonly(),
|
|
367
|
+
/** @type {() => Amount<'nat'>} */
|
|
368
|
+
// @ts-expect-error cast
|
|
369
|
+
getDebtLimit: vaultParamManager.readonly().getDebtLimit,
|
|
370
|
+
getChargingPeriod: () =>
|
|
371
|
+
loanTimingParams[CHARGING_PERIOD_KEY].value,
|
|
372
|
+
getRecordingPeriod: () =>
|
|
373
|
+
loanTimingParams[RECORDING_PERIOD_KEY].value,
|
|
374
|
+
}),
|
|
375
|
+
mintAndReallocate,
|
|
376
|
+
getShortfallReporter: async () => {
|
|
377
|
+
await updateShortfallReporter();
|
|
378
|
+
return shortfallReporter;
|
|
379
|
+
},
|
|
380
|
+
burnDebt,
|
|
575
381
|
});
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
382
|
+
|
|
383
|
+
// alleged okay because used only as a diagnostic tag
|
|
384
|
+
const brandName = await E(collateralBrand).getAllegedName();
|
|
385
|
+
const collateralUnit = await unitAmount(collateralBrand);
|
|
386
|
+
|
|
387
|
+
const makeVaultManager = managerBaggages.addChild(
|
|
388
|
+
brandName,
|
|
389
|
+
prepareVaultManagerKit,
|
|
390
|
+
zcf,
|
|
391
|
+
debtMint,
|
|
392
|
+
collateralBrand,
|
|
393
|
+
collateralUnit,
|
|
394
|
+
factoryPowers,
|
|
395
|
+
startTimeStamp,
|
|
396
|
+
managerStorageNode,
|
|
397
|
+
marshaller,
|
|
398
|
+
);
|
|
399
|
+
|
|
400
|
+
const { self: vm } = makeVaultManager();
|
|
401
|
+
collateralTypes.init(collateralBrand, vm);
|
|
402
|
+
const { install, terms } = getLiquidationConfig();
|
|
403
|
+
await vm.setupLiquidator(install, terms);
|
|
404
|
+
watchGovernance(vm, install, terms);
|
|
405
|
+
facets.machine.updateMetrics();
|
|
406
|
+
return vm;
|
|
407
|
+
},
|
|
408
|
+
makeCollectFeesInvitation() {
|
|
409
|
+
return makeMakeCollectFeesInvitation(
|
|
410
|
+
zcf,
|
|
411
|
+
rewardPoolSeat,
|
|
412
|
+
debtMint.getIssuerRecord().brand,
|
|
413
|
+
'Minted',
|
|
414
|
+
).makeCollectFeesInvitation();
|
|
415
|
+
},
|
|
416
|
+
getContractGovernor() {
|
|
417
|
+
return zcf.getTerms().electionManager;
|
|
418
|
+
},
|
|
419
|
+
updateMetrics() {
|
|
420
|
+
return metricsPublisher.publish(sampleMetrics());
|
|
421
|
+
},
|
|
422
|
+
// XXX accessors for tests
|
|
423
|
+
getRewardAllocation() {
|
|
424
|
+
return rewardPoolSeat.getCurrentAllocation();
|
|
425
|
+
},
|
|
426
|
+
},
|
|
427
|
+
public: {
|
|
428
|
+
/**
|
|
429
|
+
* @param {Brand} brandIn
|
|
430
|
+
*/
|
|
431
|
+
getCollateralManager(brandIn) {
|
|
581
432
|
collateralTypes.has(brandIn) ||
|
|
582
433
|
Fail`Not a supported collateral type ${brandIn}`;
|
|
583
|
-
|
|
584
|
-
AmountMath.isGTE(
|
|
585
|
-
requestedAmount,
|
|
586
|
-
ephemera.directorParamManager.getMinInitialDebt(),
|
|
587
|
-
) ||
|
|
588
|
-
Fail`The request must be for at least ${
|
|
589
|
-
ephemera.directorParamManager.getMinInitialDebt().value
|
|
590
|
-
}. ${requestedAmount.value} is too small`;
|
|
591
|
-
|
|
592
434
|
/** @type {VaultManager} */
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
435
|
+
return collateralTypes.get(brandIn).getPublicFacet();
|
|
436
|
+
},
|
|
437
|
+
/**
|
|
438
|
+
* @deprecated get `collaterals` list from metrics
|
|
439
|
+
*/
|
|
440
|
+
async getCollaterals() {
|
|
441
|
+
// should be collateralTypes.map((vm, brand) => ({
|
|
442
|
+
return harden(
|
|
443
|
+
Promise.all(
|
|
444
|
+
[...collateralTypes.entries()].map(async ([brand, vm]) => {
|
|
445
|
+
const priceQuote = await vm.getCollateralQuote();
|
|
446
|
+
return {
|
|
447
|
+
brand,
|
|
448
|
+
interestRate: vm.getGovernedParams().getInterestRate(),
|
|
449
|
+
liquidationMargin: vm
|
|
450
|
+
.getGovernedParams()
|
|
451
|
+
.getLiquidationMargin(),
|
|
452
|
+
stabilityFee: vm.getGovernedParams().getLoanFee(),
|
|
453
|
+
marketPrice: makeRatioFromAmounts(
|
|
454
|
+
getAmountOut(priceQuote),
|
|
455
|
+
getAmountIn(priceQuote),
|
|
456
|
+
),
|
|
457
|
+
};
|
|
458
|
+
}),
|
|
459
|
+
),
|
|
460
|
+
);
|
|
461
|
+
},
|
|
462
|
+
getMetrics() {
|
|
463
|
+
return storedMetricsSubscriber;
|
|
464
|
+
},
|
|
465
|
+
/**
|
|
466
|
+
* @deprecated use getCollateralManager and then makeVaultInvitation instead
|
|
467
|
+
*
|
|
468
|
+
* Make a vault in the vaultManager based on the collateral type.
|
|
469
|
+
*/
|
|
470
|
+
makeVaultInvitation() {
|
|
471
|
+
/** @param {ZCFSeat} seat */
|
|
472
|
+
const makeVaultHook = async seat => {
|
|
473
|
+
assertProposalShape(seat, {
|
|
474
|
+
give: { Collateral: null },
|
|
475
|
+
want: { Minted: null },
|
|
476
|
+
});
|
|
477
|
+
const {
|
|
478
|
+
give: { Collateral: collateralAmount },
|
|
479
|
+
want: { Minted: requestedAmount },
|
|
480
|
+
} = seat.getProposal();
|
|
481
|
+
const { brand: brandIn } = collateralAmount;
|
|
482
|
+
collateralTypes.has(brandIn) ||
|
|
483
|
+
Fail`Not a supported collateral type ${brandIn}`;
|
|
484
|
+
|
|
485
|
+
AmountMath.isGTE(
|
|
486
|
+
requestedAmount,
|
|
487
|
+
directorParamManager.getMinInitialDebt(),
|
|
488
|
+
) ||
|
|
489
|
+
Fail`The request must be for at least ${
|
|
490
|
+
directorParamManager.getMinInitialDebt().value
|
|
491
|
+
}. ${requestedAmount.value} is too small`;
|
|
492
|
+
|
|
493
|
+
/** @type {VaultManager} */
|
|
494
|
+
const mgr = collateralTypes.get(brandIn);
|
|
495
|
+
return mgr.makeVaultKit(seat);
|
|
496
|
+
};
|
|
497
|
+
return zcf.makeInvitation(makeVaultHook, 'MakeVault');
|
|
498
|
+
},
|
|
499
|
+
getRunIssuer() {
|
|
500
|
+
return debtMint.getIssuerRecord().issuer;
|
|
501
|
+
},
|
|
502
|
+
/**
|
|
503
|
+
* subscription for the paramManager for a particular vaultManager
|
|
504
|
+
*
|
|
505
|
+
* @param {{ collateralBrand: Brand }} selector
|
|
506
|
+
*/
|
|
507
|
+
getSubscription({ collateralBrand }) {
|
|
508
|
+
return vaultParamManagers.get(collateralBrand).getSubscription();
|
|
509
|
+
},
|
|
510
|
+
/**
|
|
511
|
+
* subscription for the paramManager for the vaultFactory's electorate
|
|
512
|
+
*/
|
|
513
|
+
getElectorateSubscription() {
|
|
514
|
+
return directorParamManager.getSubscription();
|
|
515
|
+
},
|
|
516
|
+
/**
|
|
517
|
+
* @param {{ collateralBrand: Brand }} selector
|
|
518
|
+
*/
|
|
519
|
+
getGovernedParams({ collateralBrand }) {
|
|
520
|
+
// TODO use named getters of TypedParamManager
|
|
521
|
+
return vaultParamManagers.get(collateralBrand).getParams();
|
|
522
|
+
},
|
|
523
|
+
/**
|
|
524
|
+
* @returns {Promise<GovernorPublic>}
|
|
525
|
+
*/
|
|
526
|
+
getContractGovernor() {
|
|
527
|
+
// PERF consider caching
|
|
528
|
+
return E(zcf.getZoeService()).getPublicFacet(
|
|
529
|
+
zcf.getTerms().electionManager,
|
|
530
|
+
);
|
|
531
|
+
},
|
|
532
|
+
/**
|
|
533
|
+
* @param {string} name
|
|
534
|
+
*/
|
|
535
|
+
getInvitationAmount(name) {
|
|
536
|
+
return directorParamManager.getInvitationAmount(name);
|
|
537
|
+
},
|
|
638
538
|
},
|
|
639
539
|
},
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
harden(
|
|
645
|
-
export { makeVaultDirector };
|
|
540
|
+
{ finish },
|
|
541
|
+
);
|
|
542
|
+
return makeVaultDirector;
|
|
543
|
+
};
|
|
544
|
+
harden(prepareVaultDirector);
|