@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.
- package/README.md +26 -20
- package/bundles/bundle-auctioneer-js-meta.json +722 -0
- package/bundles/bundle-auctioneer.js +1 -0
- package/bundles/bundle-econCommitteeCharter-js-meta.json +514 -0
- package/bundles/bundle-econCommitteeCharter.js +1 -0
- package/bundles/bundle-feeDistributor-js-meta.json +458 -0
- package/bundles/bundle-feeDistributor.js +1 -1
- package/bundles/bundle-fluxAggregatorKit-js-meta.json +674 -0
- package/bundles/bundle-fluxAggregatorKit.js +1 -0
- package/bundles/bundle-psm-js-meta.json +666 -0
- package/bundles/bundle-psm.js +1 -1
- package/bundles/bundle-reserve-js-meta.json +662 -0
- package/bundles/bundle-reserve.js +1 -1
- package/bundles/bundle-scaledPriceAuthority-js-meta.json +542 -0
- package/bundles/bundle-scaledPriceAuthority.js +1 -1
- package/bundles/bundle-vaultFactory-js-meta.json +786 -0
- package/bundles/bundle-vaultFactory.js +1 -1
- package/exported.js +0 -2
- package/package.json +34 -31
- package/scripts/add-collateral-core.js +14 -4
- package/scripts/build-bundles.js +9 -2
- package/scripts/deploy-contracts.js +1 -4
- package/scripts/init-core.js +20 -38
- package/scripts/invite-committee-core.js +1 -1
- package/scripts/manual-price-feed.js +2 -2
- package/scripts/price-feed-core.js +7 -6
- package/scripts/start-local-chain.sh +84 -0
- package/src/auction/auctionBook.js +755 -0
- package/src/auction/auctioneer.js +720 -0
- package/src/auction/offerBook.js +221 -0
- package/src/auction/params.js +174 -0
- package/src/auction/scheduleMath.js +167 -0
- package/src/auction/scheduler.js +370 -0
- package/src/auction/sortedOffers.js +136 -0
- package/src/auction/util.js +55 -0
- package/src/clientSupport.js +324 -0
- package/src/collectFees.js +8 -14
- package/src/contractSupport.js +24 -68
- package/src/econCommitteeCharter.js +161 -77
- package/src/feeDistributor.js +60 -20
- package/src/index.js +2 -0
- package/src/interest-math.js +1 -4
- package/src/interest.js +20 -13
- package/src/price/README.md +57 -0
- package/src/price/fluxAggregatorContract.js +190 -0
- package/src/price/fluxAggregatorKit.js +375 -0
- package/src/price/priceOracleKit.js +127 -0
- package/src/price/roundsManager.js +726 -0
- package/src/proposals/addAssetToVault.js +89 -94
- package/src/proposals/committee-proposal.js +141 -40
- package/src/proposals/core-proposal.js +100 -167
- package/src/proposals/econ-behaviors.js +320 -564
- package/src/proposals/price-feed-proposal.js +175 -78
- package/src/proposals/startEconCommittee.js +25 -12
- package/src/proposals/startPSM.js +231 -211
- package/src/proposals/utils.js +31 -17
- package/src/psm/README.md +71 -0
- package/src/psm/psm.js +272 -160
- package/src/psm/types.js +2 -0
- package/src/reserve/assetReserve.js +56 -413
- package/src/reserve/assetReserveKit.js +303 -0
- package/src/reserve/doc.md +1 -3
- package/src/reserve/params.js +2 -5
- package/src/typeGuards.js +13 -0
- package/src/vaultFactory/Liquidation.md +100 -0
- package/src/vaultFactory/burn.js +2 -1
- package/src/vaultFactory/liquidation.js +270 -108
- package/src/vaultFactory/math.js +95 -0
- package/src/vaultFactory/orderedVaultStore.js +0 -1
- package/src/vaultFactory/params.js +133 -112
- package/src/vaultFactory/prioritizedVaults.js +36 -79
- package/src/vaultFactory/storeUtils.js +67 -9
- package/src/vaultFactory/type-imports.js +2 -0
- package/src/vaultFactory/types.js +22 -26
- package/src/vaultFactory/vault.js +772 -709
- package/src/vaultFactory/vaultDirector.js +480 -483
- package/src/vaultFactory/vaultFactory.js +99 -60
- package/src/vaultFactory/vaultHolder.js +121 -95
- package/src/vaultFactory/vaultKit.js +39 -31
- package/src/vaultFactory/vaultManager.js +1249 -868
- package/bundles/bundle-amm-meta.js +0 -618
- package/bundles/bundle-amm.js +0 -1
- package/bundles/bundle-feeDistributor-meta.js +0 -346
- package/bundles/bundle-interchainPool-meta.js +0 -534
- package/bundles/bundle-interchainPool.js +0 -1
- package/bundles/bundle-liquidateIncrementally-meta.js +0 -442
- package/bundles/bundle-liquidateIncrementally.js +0 -1
- package/bundles/bundle-liquidateMinimum-meta.js +0 -442
- package/bundles/bundle-liquidateMinimum.js +0 -1
- package/bundles/bundle-psm-meta.js +0 -538
- package/bundles/bundle-psmCharter-meta.js +0 -418
- package/bundles/bundle-psmCharter.js +0 -1
- package/bundles/bundle-reserve-meta.js +0 -542
- package/bundles/bundle-scaledPriceAuthority-meta.js +0 -442
- package/bundles/bundle-stakeFactory-meta.js +0 -574
- package/bundles/bundle-stakeFactory.js +0 -1
- package/bundles/bundle-vaultFactory-meta.js +0 -598
- package/scripts/add-initial-liquidity.js +0 -180
- package/src/collect.js +0 -13
- package/src/interchainPool.js +0 -135
- package/src/makeTracer.js +0 -36
- package/src/my-lien.js +0 -85
- package/src/proposals/demoIssuers.js +0 -685
- package/src/proposals/sim-behaviors.js +0 -40
- package/src/psm/psmCharter.js +0 -139
- package/src/stakeFactory/README.md +0 -62
- package/src/stakeFactory/attestation.js +0 -267
- package/src/stakeFactory/attestationTool.js +0 -66
- package/src/stakeFactory/constants.js +0 -16
- package/src/stakeFactory/params.js +0 -31
- package/src/stakeFactory/stakeFactory.js +0 -236
- package/src/stakeFactory/stakeFactoryKit.js +0 -455
- package/src/stakeFactory/stakeFactoryManager.js +0 -296
- package/src/stakeFactory/types.js +0 -42
- package/src/vaultFactory/liquidateIncrementally.js +0 -350
- package/src/vaultFactory/liquidateMinimum.js +0 -100
- package/src/vpool-xyk-amm/AttackersGuide.md +0 -89
- package/src/vpool-xyk-amm/addLiquidity.js +0 -222
- package/src/vpool-xyk-amm/addPool.js +0 -197
- package/src/vpool-xyk-amm/constantProduct/AMM-Trade.jpeg +0 -0
- package/src/vpool-xyk-amm/constantProduct/README.md +0 -204
- package/src/vpool-xyk-amm/constantProduct/calcFees.js +0 -99
- package/src/vpool-xyk-amm/constantProduct/calcSwapPrices.js +0 -85
- package/src/vpool-xyk-amm/constantProduct/core.js +0 -153
- package/src/vpool-xyk-amm/constantProduct/defaults.js +0 -5
- package/src/vpool-xyk-amm/constantProduct/getXY.js +0 -52
- package/src/vpool-xyk-amm/constantProduct/internal-types.js +0 -116
- package/src/vpool-xyk-amm/constantProduct/invariants.js +0 -43
- package/src/vpool-xyk-amm/constantProduct/swap.js +0 -272
- package/src/vpool-xyk-amm/constantProduct/types.js +0 -32
- package/src/vpool-xyk-amm/doublePool.js +0 -194
- package/src/vpool-xyk-amm/estimate.js +0 -155
- package/src/vpool-xyk-amm/multipoolMarketMaker.js +0 -520
- package/src/vpool-xyk-amm/params.js +0 -61
- package/src/vpool-xyk-amm/pool.js +0 -396
- package/src/vpool-xyk-amm/priceAuthority.js +0 -94
- package/src/vpool-xyk-amm/removeLiquidity.js +0 -31
- package/src/vpool-xyk-amm/singlePool.js +0 -73
- package/src/vpool-xyk-amm/swap.js +0 -69
- 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/
|
|
7
|
-
import { E } from '@endo/eventual-send';
|
|
4
|
+
import '@agoric/governance/exported.js';
|
|
8
5
|
|
|
9
|
-
import {
|
|
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
|
-
|
|
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 {
|
|
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
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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
|
-
|
|
30
|
-
makeVaultParamManager,
|
|
31
|
-
RECORDING_PERIOD_KEY,
|
|
35
|
+
provideVaultParamManagers,
|
|
32
36
|
SHORTFALL_INVITATION_KEY,
|
|
33
37
|
vaultParamPattern,
|
|
34
38
|
} from './params.js';
|
|
35
|
-
import {
|
|
36
|
-
|
|
37
|
-
|
|
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
|
-
|
|
54
|
-
|
|
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
|
-
*
|
|
62
|
+
* @typedef {{
|
|
83
63
|
* burnDebt: BurnDebt,
|
|
84
|
-
* getGovernedParams: () => import('./vaultManager.js').GovernedParamGetters,
|
|
85
|
-
*
|
|
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 {
|
|
146
|
-
* @param {
|
|
147
|
-
* @param {
|
|
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
|
-
* @
|
|
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
|
|
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
|
-
/**
|
|
160
|
-
|
|
161
|
-
const { zcfSeat: rewardPoolSeat } = zcf.makeEmptySeatKit();
|
|
102
|
+
/** @type {import('../reserve/assetReserve.js').ShortfallReporter} */
|
|
103
|
+
let shortfallReporter;
|
|
162
104
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
});
|
|
105
|
+
/** For holding newly minted tokens until transferred */
|
|
106
|
+
const { zcfSeat: mintSeat } = zcf.makeEmptySeatKit();
|
|
166
107
|
|
|
167
|
-
|
|
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
|
-
|
|
172
|
-
|
|
173
|
-
|
|
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
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
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
|
-
|
|
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
|
-
|
|
242
|
-
|
|
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
|
-
* @
|
|
302
|
-
* @param {Issuer} collateralIssuer
|
|
303
|
-
* @param {Keyword} collateralKeyword
|
|
304
|
-
* @param {VaultManagerParamValues} initialParamValues
|
|
133
|
+
* @returns {MetricsNotification}
|
|
305
134
|
*/
|
|
306
|
-
|
|
307
|
-
{
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
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
|
-
|
|
345
|
-
|
|
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
|
-
*
|
|
349
|
-
*
|
|
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
|
-
* @
|
|
175
|
+
* @param {Brand} brand
|
|
352
176
|
*/
|
|
353
|
-
|
|
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
|
-
|
|
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('
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
//
|
|
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
|
-
|
|
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
|
-
|
|
228
|
+
burnDebt: (toBurn, seat) => {
|
|
391
229
|
debtMint.burnLosses(harden({ Minted: toBurn }), seat);
|
|
392
|
-
}
|
|
230
|
+
},
|
|
231
|
+
});
|
|
393
232
|
|
|
394
|
-
|
|
233
|
+
const makeVaultManagerKit = prepareVaultManagerKit(baggage, {
|
|
234
|
+
makeERecorderKit,
|
|
235
|
+
makeRecorderKit,
|
|
236
|
+
marshaller,
|
|
237
|
+
factoryPowers,
|
|
238
|
+
zcf,
|
|
239
|
+
});
|
|
395
240
|
|
|
396
|
-
|
|
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
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
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
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
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
|
-
* @
|
|
486
|
-
* @param {Brand} brandIn
|
|
270
|
+
* @returns {State}
|
|
487
271
|
*/
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
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
|
-
*
|
|
277
|
+
* "Director" of the vault factory, overseeing "vault managers".
|
|
505
278
|
*
|
|
506
|
-
* @param {
|
|
507
|
-
* @param {
|
|
279
|
+
* @param {import('./vaultFactory.js').VaultFactoryZCF} zcf
|
|
280
|
+
* @param {VaultDirectorParamManager} directorParamManager
|
|
281
|
+
* @param {ZCFMint<"nat">} debtMint
|
|
508
282
|
*/
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
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
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
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
|
-
*
|
|
565
|
+
* Prepare the VaultDirector kind, get or make the singleton
|
|
559
566
|
*
|
|
560
|
-
* @
|
|
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
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
);
|
|
577
|
-
|
|
578
|
-
harden(
|
|
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);
|