@agoric/inter-protocol 0.13.3 → 0.13.4-dev-800c2bb.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
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
import { Fail } from '@agoric/assert';
|
|
2
|
+
import { AmountMath, AmountShape, IssuerShape } from '@agoric/ertp';
|
|
3
|
+
import { makeTracer } from '@agoric/internal';
|
|
4
|
+
import { M, makeScalarBigMapStore, prepareExoClassKit } from '@agoric/vat-data';
|
|
5
|
+
import { atomicTransfer } from '@agoric/zoe/src/contractSupport/atomicTransfer.js';
|
|
6
|
+
import {
|
|
7
|
+
makeRecorderTopic,
|
|
8
|
+
SubscriberShape,
|
|
9
|
+
TopicsRecordShape,
|
|
10
|
+
} from '@agoric/zoe/src/contractSupport/topics.js';
|
|
11
|
+
import { AmountKeywordRecordShape } from '@agoric/zoe/src/typeGuards.js';
|
|
12
|
+
import { E } from '@endo/eventual-send';
|
|
13
|
+
import { UnguardedHelperI } from '../typeGuards.js';
|
|
14
|
+
|
|
15
|
+
const { quote: q } = assert;
|
|
16
|
+
|
|
17
|
+
const trace = makeTracer('ReserveKit', true);
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @typedef {object} MetricsNotification
|
|
21
|
+
*
|
|
22
|
+
* @property {AmountKeywordRecord} allocations
|
|
23
|
+
* @property {Amount<'nat'>} shortfallBalance shortfall from liquidation that
|
|
24
|
+
* has not yet been compensated.
|
|
25
|
+
* @property {Amount<'nat'>} totalFeeMinted total Fee tokens minted to date
|
|
26
|
+
* @property {Amount<'nat'>} totalFeeBurned total Fee tokens burned to date
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @param {import('@agoric/vat-data').Baggage} baggage
|
|
31
|
+
* @param {{
|
|
32
|
+
* feeMint: ZCFMint<'nat'>,
|
|
33
|
+
* makeRecorderKit: import('@agoric/zoe/src/contractSupport/recorder.js').MakeRecorderKit,
|
|
34
|
+
* storageNode: StorageNode,
|
|
35
|
+
* zcf: ZCF}} powers
|
|
36
|
+
*/
|
|
37
|
+
export const prepareAssetReserveKit = async (
|
|
38
|
+
baggage,
|
|
39
|
+
{ feeMint, makeRecorderKit, storageNode, zcf },
|
|
40
|
+
) => {
|
|
41
|
+
trace('prepareAssetReserveKit', [...baggage.keys()]);
|
|
42
|
+
const feeKit = feeMint.getIssuerRecord();
|
|
43
|
+
const emptyAmount = AmountMath.makeEmpty(feeKit.brand);
|
|
44
|
+
|
|
45
|
+
const makeAssetReserveKitInternal = prepareExoClassKit(
|
|
46
|
+
baggage,
|
|
47
|
+
'AssetReserveKit',
|
|
48
|
+
{
|
|
49
|
+
helper: UnguardedHelperI,
|
|
50
|
+
governedApis: M.interface('AssetReserve governedApis', {
|
|
51
|
+
burnFeesToReduceShortfall: M.call(AmountShape).returns(),
|
|
52
|
+
}),
|
|
53
|
+
machine: M.interface('AssetReserve machine', {
|
|
54
|
+
addIssuer: M.call(IssuerShape, M.string()).returns(M.promise()),
|
|
55
|
+
getAllocations: M.call().returns(AmountKeywordRecordShape),
|
|
56
|
+
makeShortfallReportingInvitation: M.call().returns(M.promise()),
|
|
57
|
+
}),
|
|
58
|
+
public: M.interface('AssetReserve public', {
|
|
59
|
+
makeAddCollateralInvitation: M.call().returns(M.promise()),
|
|
60
|
+
getMetrics: M.call().returns(SubscriberShape),
|
|
61
|
+
getPublicTopics: M.call().returns(TopicsRecordShape),
|
|
62
|
+
}),
|
|
63
|
+
shortfallReportingFacet: M.interface('AssetReserve shortfall reporter', {
|
|
64
|
+
increaseLiquidationShortfall: M.call(AmountShape).returns(),
|
|
65
|
+
reduceLiquidationShortfall: M.call(AmountShape).returns(),
|
|
66
|
+
}),
|
|
67
|
+
},
|
|
68
|
+
/**
|
|
69
|
+
*
|
|
70
|
+
* @param {StorageNode} metricsNode
|
|
71
|
+
*/
|
|
72
|
+
metricsNode => {
|
|
73
|
+
/**
|
|
74
|
+
* Used to look up the unique keyword for each brand, including Fee brand.
|
|
75
|
+
*
|
|
76
|
+
* @type {MapStore<Brand, Keyword>}
|
|
77
|
+
*/
|
|
78
|
+
const keywordForBrand = makeScalarBigMapStore('keywordForBrand', {
|
|
79
|
+
durable: true,
|
|
80
|
+
});
|
|
81
|
+
/**
|
|
82
|
+
* Used to look up the brands for keywords, excluding Fee because it's a special case.
|
|
83
|
+
*
|
|
84
|
+
* @type {MapStore<Keyword, Brand>}
|
|
85
|
+
*/
|
|
86
|
+
const brandForKeyword = makeScalarBigMapStore('brandForKeyword', {
|
|
87
|
+
durable: true,
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
return {
|
|
91
|
+
brandForKeyword,
|
|
92
|
+
// We keep the associated liquidity tokens in the same seat
|
|
93
|
+
collateralSeat: zcf.makeEmptySeatKit().zcfSeat,
|
|
94
|
+
keywordForBrand,
|
|
95
|
+
metricsKit: makeRecorderKit(
|
|
96
|
+
metricsNode,
|
|
97
|
+
/** @type {import('@agoric/zoe/src/contractSupport/recorder.js').TypedMatcher<MetricsNotification>} */ (
|
|
98
|
+
M.any()
|
|
99
|
+
),
|
|
100
|
+
),
|
|
101
|
+
totalFeeMinted: emptyAmount,
|
|
102
|
+
totalFeeBurned: emptyAmount,
|
|
103
|
+
shortfallBalance: emptyAmount,
|
|
104
|
+
};
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
helper: {
|
|
108
|
+
/** @param {Brand} brand */
|
|
109
|
+
getKeywordForBrand(brand) {
|
|
110
|
+
const { keywordForBrand } = this.state;
|
|
111
|
+
keywordForBrand.has(brand) ||
|
|
112
|
+
Fail`Issuer not defined for brand ${q(
|
|
113
|
+
brand,
|
|
114
|
+
)}; first call addIssuer()`;
|
|
115
|
+
return keywordForBrand.get(brand);
|
|
116
|
+
},
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* @param {Brand} brand
|
|
120
|
+
* @param {Keyword} keyword
|
|
121
|
+
*/
|
|
122
|
+
saveBrandKeyword(brand, keyword) {
|
|
123
|
+
trace('saveBrandKeyword', brand, keyword);
|
|
124
|
+
const { keywordForBrand, brandForKeyword } = this.state;
|
|
125
|
+
keywordForBrand.init(brand, keyword);
|
|
126
|
+
brandForKeyword.init(keyword, brand);
|
|
127
|
+
},
|
|
128
|
+
|
|
129
|
+
writeMetrics() {
|
|
130
|
+
const { state } = this;
|
|
131
|
+
const metrics = harden({
|
|
132
|
+
allocations: state.collateralSeat.getCurrentAllocation(),
|
|
133
|
+
shortfallBalance: state.shortfallBalance,
|
|
134
|
+
totalFeeMinted: state.totalFeeMinted,
|
|
135
|
+
totalFeeBurned: state.totalFeeBurned,
|
|
136
|
+
});
|
|
137
|
+
void state.metricsKit.recorder.write(metrics);
|
|
138
|
+
},
|
|
139
|
+
},
|
|
140
|
+
governedApis: {
|
|
141
|
+
/**
|
|
142
|
+
*
|
|
143
|
+
* @param {Amount<'nat'>} reduction
|
|
144
|
+
* @returns {void}
|
|
145
|
+
*/
|
|
146
|
+
burnFeesToReduceShortfall(reduction) {
|
|
147
|
+
const { facets, state } = this;
|
|
148
|
+
trace('burnFeesToReduceShortfall', reduction);
|
|
149
|
+
reduction = AmountMath.coerce(feeKit.brand, reduction);
|
|
150
|
+
const feeKeyword = state.keywordForBrand.get(feeKit.brand);
|
|
151
|
+
const feeBalance =
|
|
152
|
+
state.collateralSeat.getAmountAllocated(feeKeyword);
|
|
153
|
+
const amountToBurn = AmountMath.min(reduction, feeBalance);
|
|
154
|
+
if (AmountMath.isEmpty(amountToBurn)) {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
feeMint.burnLosses(
|
|
159
|
+
harden({ [feeKeyword]: amountToBurn }),
|
|
160
|
+
state.collateralSeat,
|
|
161
|
+
);
|
|
162
|
+
state.totalFeeBurned = AmountMath.add(
|
|
163
|
+
state.totalFeeBurned,
|
|
164
|
+
amountToBurn,
|
|
165
|
+
);
|
|
166
|
+
facets.helper.writeMetrics();
|
|
167
|
+
},
|
|
168
|
+
},
|
|
169
|
+
machine: {
|
|
170
|
+
// add makeRedeemLiquidityTokensInvitation later. For now just store them
|
|
171
|
+
/**
|
|
172
|
+
* @param {Issuer} issuer
|
|
173
|
+
* @param {string} keyword
|
|
174
|
+
*/
|
|
175
|
+
async addIssuer(issuer, keyword) {
|
|
176
|
+
const brand = await E(issuer).getBrand();
|
|
177
|
+
trace('addIssuer', { brand, keyword });
|
|
178
|
+
assert(
|
|
179
|
+
keyword !== 'Fee' && brand !== feeKit.brand,
|
|
180
|
+
`'Fee' brand is a special case handled by the reserve contract`,
|
|
181
|
+
);
|
|
182
|
+
|
|
183
|
+
trace('addIssuer storing', {
|
|
184
|
+
keyword,
|
|
185
|
+
brand,
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
this.facets.helper.saveBrandKeyword(brand, keyword);
|
|
189
|
+
await zcf.saveIssuer(issuer, keyword);
|
|
190
|
+
},
|
|
191
|
+
|
|
192
|
+
/** @deprecated use getPublicTopics metrics allocation */
|
|
193
|
+
getAllocations() {
|
|
194
|
+
return this.state.collateralSeat.getCurrentAllocation();
|
|
195
|
+
},
|
|
196
|
+
|
|
197
|
+
makeShortfallReportingInvitation() {
|
|
198
|
+
const { facets } = this;
|
|
199
|
+
const handleShortfallReportingOffer = () => {
|
|
200
|
+
return facets.shortfallReportingFacet;
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
return zcf.makeInvitation(
|
|
204
|
+
handleShortfallReportingOffer,
|
|
205
|
+
'getFacetForReportingShortfalls',
|
|
206
|
+
);
|
|
207
|
+
},
|
|
208
|
+
},
|
|
209
|
+
/**
|
|
210
|
+
* XXX missing governance public methods https://github.com/Agoric/agoric-sdk/issues/5200
|
|
211
|
+
*/
|
|
212
|
+
public: {
|
|
213
|
+
/**
|
|
214
|
+
* Anyone can deposit any assets to the reserve
|
|
215
|
+
*/
|
|
216
|
+
makeAddCollateralInvitation() {
|
|
217
|
+
/** @type {OfferHandler<Promise<string>>} */
|
|
218
|
+
const handler = async seat => {
|
|
219
|
+
const {
|
|
220
|
+
give: { Collateral: amountIn },
|
|
221
|
+
} = seat.getProposal();
|
|
222
|
+
const { facets, state } = this;
|
|
223
|
+
const { helper } = facets;
|
|
224
|
+
|
|
225
|
+
const collateralKeyword = helper.getKeywordForBrand(amountIn.brand);
|
|
226
|
+
|
|
227
|
+
atomicTransfer(
|
|
228
|
+
zcf,
|
|
229
|
+
seat,
|
|
230
|
+
state.collateralSeat,
|
|
231
|
+
{ Collateral: amountIn },
|
|
232
|
+
{ [collateralKeyword]: amountIn },
|
|
233
|
+
);
|
|
234
|
+
seat.exit();
|
|
235
|
+
helper.writeMetrics();
|
|
236
|
+
|
|
237
|
+
trace('received collateral', amountIn);
|
|
238
|
+
return 'added Collateral to the Reserve';
|
|
239
|
+
};
|
|
240
|
+
return zcf.makeInvitation(handler, 'Add Collateral');
|
|
241
|
+
},
|
|
242
|
+
/** @deprecated */
|
|
243
|
+
getMetrics() {
|
|
244
|
+
return this.state.metricsKit.subscriber;
|
|
245
|
+
},
|
|
246
|
+
getPublicTopics() {
|
|
247
|
+
return {
|
|
248
|
+
metrics: makeRecorderTopic(
|
|
249
|
+
'Asset Reserve metrics',
|
|
250
|
+
this.state.metricsKit,
|
|
251
|
+
),
|
|
252
|
+
};
|
|
253
|
+
},
|
|
254
|
+
},
|
|
255
|
+
shortfallReportingFacet: {
|
|
256
|
+
/**
|
|
257
|
+
* @param {Amount<"nat">} shortfall
|
|
258
|
+
*/
|
|
259
|
+
increaseLiquidationShortfall(shortfall) {
|
|
260
|
+
const { facets, state } = this;
|
|
261
|
+
state.shortfallBalance = AmountMath.add(
|
|
262
|
+
state.shortfallBalance,
|
|
263
|
+
shortfall,
|
|
264
|
+
);
|
|
265
|
+
facets.helper.writeMetrics();
|
|
266
|
+
},
|
|
267
|
+
|
|
268
|
+
// currently exposed for testing. Maybe it only gets called internally?
|
|
269
|
+
/**
|
|
270
|
+
* @param {Amount<"nat">} reduction
|
|
271
|
+
*/
|
|
272
|
+
reduceLiquidationShortfall(reduction) {
|
|
273
|
+
const { state } = this;
|
|
274
|
+
if (AmountMath.isGTE(reduction, state.shortfallBalance)) {
|
|
275
|
+
state.shortfallBalance = emptyAmount;
|
|
276
|
+
} else {
|
|
277
|
+
state.shortfallBalance = AmountMath.subtract(
|
|
278
|
+
state.shortfallBalance,
|
|
279
|
+
reduction,
|
|
280
|
+
);
|
|
281
|
+
}
|
|
282
|
+
this.facets.helper.writeMetrics();
|
|
283
|
+
},
|
|
284
|
+
},
|
|
285
|
+
},
|
|
286
|
+
{
|
|
287
|
+
finish: ({ facets: { helper } }) => {
|
|
288
|
+
// no need to saveIssuer() b/c registerFeeMint did it
|
|
289
|
+
helper.saveBrandKeyword(feeKit.brand, 'Fee');
|
|
290
|
+
|
|
291
|
+
helper.writeMetrics();
|
|
292
|
+
},
|
|
293
|
+
},
|
|
294
|
+
);
|
|
295
|
+
|
|
296
|
+
const makeAssetReserveKit = async () => {
|
|
297
|
+
const metricsNode = await E(storageNode).makeChildNode('metrics');
|
|
298
|
+
return makeAssetReserveKitInternal(metricsNode);
|
|
299
|
+
};
|
|
300
|
+
return makeAssetReserveKit;
|
|
301
|
+
};
|
|
302
|
+
harden(prepareAssetReserveKit);
|
|
303
|
+
/** @typedef {ReturnType<Awaited<ReturnType<typeof prepareAssetReserveKit>>>} AssetReserveKit */
|
package/src/reserve/doc.md
CHANGED
|
@@ -77,9 +77,7 @@ zoe ->> addCollateralHook: call addCollateralHook
|
|
|
77
77
|
addCollateralHook ->> seat: get proposal
|
|
78
78
|
|
|
79
79
|
addCollateralHook ->> addCollateralHook: get Keyword for amountIn brand
|
|
80
|
-
addCollateralHook ->>
|
|
81
|
-
addCollateralHook ->> collateralSeat: incrementBy collateralKeyword: amountIn
|
|
82
|
-
addCollateralHook ->> zcf: reallocate collateralSeat, seat
|
|
80
|
+
addCollateralHook ->> zcf: atomicTransfer amountIn from seat to collateralSeat
|
|
83
81
|
addCollateralHook ->> seat: seat.exit()
|
|
84
82
|
seat ->> zoe: added collateral to the reserve
|
|
85
83
|
zoe ->> caller: return status
|
package/src/reserve/params.js
CHANGED
|
@@ -1,13 +1,10 @@
|
|
|
1
|
-
// @
|
|
1
|
+
// @jessie-check
|
|
2
2
|
|
|
3
3
|
import { CONTRACT_ELECTORATE, ParamTypes } from '@agoric/governance';
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const makeReserveTerms = (poserInvitationAmount, ammInstance, timer) => ({
|
|
5
|
+
const makeReserveTerms = (poserInvitationAmount, timer) => ({
|
|
8
6
|
timer,
|
|
9
7
|
governedParams: harden({
|
|
10
|
-
[AMM_INSTANCE]: { type: ParamTypes.INSTANCE, value: ammInstance },
|
|
11
8
|
[CONTRACT_ELECTORATE]: {
|
|
12
9
|
type: ParamTypes.INVITATION,
|
|
13
10
|
value: poserInvitationAmount,
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// @jessie-check
|
|
2
|
+
|
|
3
|
+
import { M } from '@agoric/store';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* To be used only for 'helper' facets where the calls are from trusted code.
|
|
7
|
+
*/
|
|
8
|
+
export const UnguardedHelperI = M.interface(
|
|
9
|
+
'helper',
|
|
10
|
+
{},
|
|
11
|
+
// not exposed so sloppy okay
|
|
12
|
+
{ sloppy: true },
|
|
13
|
+
);
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
The liquidation approach relies on a descending clock auction (a
|
|
2
|
+
"dutch" auction). The auction runs at a rate controlled by governed
|
|
3
|
+
parameters. Every auction period, each vaultManager checks to see which
|
|
4
|
+
vaults are under-water compared to an oracle price captured before the
|
|
5
|
+
auction start. The collateral from all those illiquid vaults are sent to the
|
|
6
|
+
auction, which attempts to sell them for enough to cover their outstanding
|
|
7
|
+
debt at a discount to their value. Since they are over-collateralized this
|
|
8
|
+
should normally cover the debt and possibly return excess collateral. When
|
|
9
|
+
that is the case (flow 1, below) , we repay the debt, charge a liquidation fee,
|
|
10
|
+
and return excess collateral to the vault holders.
|
|
11
|
+
|
|
12
|
+
There are two interesting exception cases. All the collateral might be sold
|
|
13
|
+
without covering the debt (flow 2a), or there might not be enough bids to
|
|
14
|
+
purchase all the collateral (flow 2b). In the first case, vault-holders don't
|
|
15
|
+
get anything back, we burn the currency we received to cover a portion of the
|
|
16
|
+
debt, any excess collateral is sent to the reserve, and we report a shortfall.
|
|
17
|
+
|
|
18
|
+
In the second case, we can't tell whether it's due to a downturn in the
|
|
19
|
+
market or a DoS attack on the exchange. In hopes that it's not the latter, we
|
|
20
|
+
reinstate as many vaults as can be made whole, declare the rest liquidated,
|
|
21
|
+
and expect the next liquidation opportunity either to find the price has
|
|
22
|
+
recovered, or to send a possibly different set of vaults to the next auction.
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
**Flow 1: Auction raises enough IST to cover debt**
|
|
26
|
+
|
|
27
|
+
The following steps occur in this order
|
|
28
|
+
|
|
29
|
+
1. IST raised by the auction is burned to reduce debt in 1:1 ratio.
|
|
30
|
+
|
|
31
|
+
- Definitionally, this should result in zero debt. Since the auction should stop
|
|
32
|
+
when it raises enough IST, it should result in zero IST remaining as well.
|
|
33
|
+
However, if some excess IST exists, it should be transferred to the reserve.
|
|
34
|
+
|
|
35
|
+
2. From any remaining collateral, the liquidation penalty is taken and
|
|
36
|
+
transferred to the reserve.
|
|
37
|
+
|
|
38
|
+
- Liquidation penalty is calculated as debt / current oracle price at auction
|
|
39
|
+
start * liquidation penalty
|
|
40
|
+
|
|
41
|
+
3. Excess collateral - if any - is returned to vault holders
|
|
42
|
+
|
|
43
|
+
- Vault holders receive collateral back sequenced by highest collateralization
|
|
44
|
+
ratio at liquidation time first.
|
|
45
|
+
- The max amount of collateral a vault should be able to receive back is:
|
|
46
|
+
original collateral - collateral covering their share of debt (using average
|
|
47
|
+
liquidation price) - collateral covering their share of the penalty (their
|
|
48
|
+
debt / total debt \* total penalty)
|
|
49
|
+
|
|
50
|
+
**Flow 2: Auction does not raise enough to cover IST debt**
|
|
51
|
+
|
|
52
|
+
This flow further bifurcates based on whether the auction has sold all its
|
|
53
|
+
collateral asset and still has not covered the debt or has collateral
|
|
54
|
+
remaining (which simply did not receive bidders)
|
|
55
|
+
|
|
56
|
+
**Flow 2a: all collateral sold and debt is not covered**
|
|
57
|
+
|
|
58
|
+
1. IST raised by the auction is burned to reduce debt in 1:1 ratio.
|
|
59
|
+
|
|
60
|
+
- Definitionally, this should result in zero IST remaining and some debt
|
|
61
|
+
remaining.
|
|
62
|
+
|
|
63
|
+
2. Remaining debt is recorded in the reserve as a shortfall
|
|
64
|
+
|
|
65
|
+
*sequence ends; no penalty is taken and vaults receive nothing back*
|
|
66
|
+
|
|
67
|
+
**Flow 2b: collateral remains but debt is still not covered by IST raised by
|
|
68
|
+
auction end**
|
|
69
|
+
|
|
70
|
+
1. IST raised by the auction is burned to reduce debt in 1:1 ratio.
|
|
71
|
+
|
|
72
|
+
- Definitionally, this should result in zero IST remaining and some debt remaining.
|
|
73
|
+
|
|
74
|
+
2. From any remaining collateral, the liquidation penalty is taken and
|
|
75
|
+
transferred to the reserve.
|
|
76
|
+
|
|
77
|
+
- Liquidation penalty is calculated as debt / current oracle price at auction
|
|
78
|
+
start \* liquidation penalty.
|
|
79
|
+
|
|
80
|
+
_Note: there now should be debt remaining and possibly collateral remaining_
|
|
81
|
+
|
|
82
|
+
3. The vault manager now iterates through the vaults that were liquidated and
|
|
83
|
+
attempts to reconstitute them (minus collateral from the liquidation penalty)
|
|
84
|
+
starting from the best CR to worst.
|
|
85
|
+
|
|
86
|
+
- Reconstitution means full prior debt AND full prior collateral minus
|
|
87
|
+
collateral used from penalty.
|
|
88
|
+
- Collateral used for penalty = vault debt / total debt \* total liquidation penalty.
|
|
89
|
+
- Debt that is given back to a vault should be subtracted from the vault
|
|
90
|
+
manager's view of remaining liquidation debt (i.e., it shouldn't be
|
|
91
|
+
double counted)
|
|
92
|
+
- Reconstituted vaults are set to OPEN status (i.e., they are live again
|
|
93
|
+
and able to be interacted with)
|
|
94
|
+
|
|
95
|
+
4. When the vault manager reaches a vault it cannot fully reconstitute
|
|
96
|
+
(both full debt and collateral as described above), it marks that vault as
|
|
97
|
+
liquidated. It then marks all other lower CR vaults as liquidated.
|
|
98
|
+
5. Any remaining collateral is transferred to the reserve.
|
|
99
|
+
6. Any remaining debt (subtracting debt that was given back to reconstituted
|
|
100
|
+
vaults, as described above) is transferred to the reserve as shortfall.
|
package/src/vaultFactory/burn.js
CHANGED