@agoric/inter-protocol 0.17.0 → 0.17.1-upgrade-23-dev-bd79330.0.bd79330
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/package.json +23 -27
- package/source-spec-registry.js +67 -0
- package/src/auction/util.d.ts +3 -1
- package/src/auction/util.d.ts.map +1 -1
- package/src/auction/util.js +1 -2
- package/src/clientSupport.d.ts +29 -73
- package/src/clientSupport.d.ts.map +1 -1
- package/src/clientSupport.js +25 -129
- package/src/collectFees.d.ts +4 -0
- package/src/collectFees.d.ts.map +1 -1
- package/src/collectFees.js +5 -2
- package/src/contractSupport.d.ts +10 -2
- package/src/contractSupport.d.ts.map +1 -1
- package/src/contractSupport.js +8 -3
- package/src/econCommitteeCharter.d.ts +19 -8
- package/src/econCommitteeCharter.d.ts.map +1 -1
- package/src/econCommitteeCharter.js +12 -12
- package/src/feeDistributor.d.ts +56 -52
- package/src/feeDistributor.d.ts.map +1 -1
- package/src/feeDistributor.js +5 -3
- package/src/index.js +0 -3
- package/src/interest-math.d.ts +1 -0
- package/src/interest-math.d.ts.map +1 -1
- package/src/interest-math.js +1 -2
- package/src/interest.d.ts +13 -1
- package/src/interest.d.ts.map +1 -1
- package/src/interest.js +6 -3
- package/src/price/fluxAggregatorContract.d.ts +38 -14
- package/src/price/fluxAggregatorContract.d.ts.map +1 -1
- package/src/price/fluxAggregatorContract.js +26 -12
- package/src/price/fluxAggregatorKit.d.ts +18 -8
- package/src/price/fluxAggregatorKit.d.ts.map +1 -1
- package/src/price/fluxAggregatorKit.js +22 -8
- package/src/price/priceOracleKit.d.ts +3 -1
- package/src/price/priceOracleKit.d.ts.map +1 -1
- package/src/price/priceOracleKit.js +3 -1
- package/src/price/roundsManager.d.ts +15 -8
- package/src/price/roundsManager.d.ts.map +1 -1
- package/src/price/roundsManager.js +9 -2
- package/src/proposals/addAssetToVault.js +17 -105
- package/src/proposals/committee-proposal.js +14 -14
- package/src/proposals/core-proposal.js +12 -37
- package/src/proposals/deploy-price-feeds.js +12 -5
- package/src/proposals/econ-behaviors.js +23 -154
- package/src/proposals/price-feed-proposal.js +14 -4
- package/src/proposals/replace-fee-distributor.js +8 -4
- package/src/proposals/replace-scaledPriceAuthorities.js +8 -2
- package/src/proposals/replaceElectorate.js +7 -1
- package/src/proposals/startEconCommittee.js +5 -1
- package/src/proposals/startPSM.js +15 -6
- package/src/proposals/upgrade-scaledPriceAuthorities.js +5 -0
- package/src/proposals/utils.d.ts +10 -4
- package/src/proposals/utils.d.ts.map +1 -1
- package/src/proposals/utils.js +16 -8
- package/src/proposals/withdraw-reserve-proposal.js +6 -1
- package/src/provisionPool.d.ts +36 -18
- package/src/provisionPool.d.ts.map +1 -1
- package/src/provisionPool.js +19 -12
- package/src/provisionPoolKit.d.ts +29 -77
- package/src/provisionPoolKit.d.ts.map +1 -1
- package/src/provisionPoolKit.js +33 -23
- package/src/psm/psm.d.ts +36 -24
- package/src/psm/psm.d.ts.map +1 -1
- package/src/psm/psm.js +19 -15
- package/src/reserve/assetReserve.d.ts +16 -6
- package/src/reserve/assetReserve.d.ts.map +1 -1
- package/src/reserve/assetReserve.js +17 -9
- package/src/reserve/assetReserveKit.d.ts +13 -10
- package/src/reserve/assetReserveKit.d.ts.map +1 -1
- package/src/reserve/assetReserveKit.js +7 -5
- package/src/reserve/params.d.ts +1 -1
- package/src/reserve/params.d.ts.map +1 -1
- package/src/reserve/params.js +1 -3
- package/src/vaultFactory/burn.d.ts +4 -1
- package/src/vaultFactory/burn.d.ts.map +1 -1
- package/src/vaultFactory/burn.js +5 -4
- package/src/vaultFactory/math.d.ts +2 -0
- package/src/vaultFactory/math.d.ts.map +1 -1
- package/src/vaultFactory/math.js +5 -3
- package/src/vaultFactory/orderedVaultStore.d.ts +36 -36
- package/src/vaultFactory/params.d.ts +37 -10
- package/src/vaultFactory/params.d.ts.map +1 -1
- package/src/vaultFactory/params.js +34 -13
- package/src/vaultFactory/prioritizedVaults.d.ts +98 -95
- package/src/vaultFactory/prioritizedVaults.d.ts.map +1 -1
- package/src/vaultFactory/prioritizedVaults.js +3 -2
- package/src/vaultFactory/storeUtils.d.ts +8 -3
- package/src/vaultFactory/storeUtils.d.ts.map +1 -1
- package/src/vaultFactory/storeUtils.js +8 -4
- package/src/vaultFactory/{types-ambient.d.ts → types.d.ts} +40 -40
- package/src/vaultFactory/types.d.ts.map +1 -0
- package/src/vaultFactory/{types-ambient.js → types.js} +26 -25
- package/src/vaultFactory/vault.d.ts +51 -35
- package/src/vaultFactory/vault.d.ts.map +1 -1
- package/src/vaultFactory/vault.js +29 -17
- package/src/vaultFactory/vaultDirector.d.ts +102 -112
- package/src/vaultFactory/vaultDirector.d.ts.map +1 -1
- package/src/vaultFactory/vaultDirector.js +40 -82
- package/src/vaultFactory/vaultFactory.d.ts +47 -95
- package/src/vaultFactory/vaultFactory.d.ts.map +1 -1
- package/src/vaultFactory/vaultFactory.js +27 -27
- package/src/vaultFactory/vaultHolder.d.ts +62 -55
- package/src/vaultFactory/vaultHolder.d.ts.map +1 -1
- package/src/vaultFactory/vaultHolder.js +10 -4
- package/src/vaultFactory/vaultKit.d.ts +15 -10
- package/src/vaultFactory/vaultKit.d.ts.map +1 -1
- package/src/vaultFactory/vaultKit.js +8 -7
- package/src/vaultFactory/vaultManager.d.ts +112 -262
- package/src/vaultFactory/vaultManager.d.ts.map +1 -1
- package/src/vaultFactory/vaultManager.js +42 -319
- package/NEWS.md +0 -0
- package/scripts/build-bundles.js +0 -22
- package/src/auction/auctionBook.d.ts +0 -147
- package/src/auction/auctionBook.d.ts.map +0 -1
- package/src/auction/auctionBook.js +0 -794
- package/src/auction/auctionMath.d.ts +0 -17
- package/src/auction/auctionMath.d.ts.map +0 -1
- package/src/auction/auctionMath.js +0 -81
- package/src/auction/auctioneer.d.ts +0 -70
- package/src/auction/auctioneer.d.ts.map +0 -1
- package/src/auction/auctioneer.js +0 -733
- package/src/auction/offerBook.d.ts +0 -46
- package/src/auction/offerBook.d.ts.map +0 -1
- package/src/auction/offerBook.js +0 -226
- package/src/auction/params.d.ts +0 -145
- package/src/auction/params.d.ts.map +0 -1
- package/src/auction/params.js +0 -176
- package/src/auction/scheduleMath.d.ts +0 -5
- package/src/auction/scheduleMath.d.ts.map +0 -1
- package/src/auction/scheduleMath.js +0 -169
- package/src/auction/scheduler.d.ts +0 -50
- package/src/auction/scheduler.d.ts.map +0 -1
- package/src/auction/scheduler.js +0 -376
- package/src/auction/sortedOffers.d.ts +0 -8
- package/src/auction/sortedOffers.d.ts.map +0 -1
- package/src/auction/sortedOffers.js +0 -137
- package/src/proposals/add-auction.js +0 -285
- package/src/proposals/upgrade-vaults.js +0 -207
- package/src/psm/types-ambient.d.ts +0 -2
- package/src/psm/types-ambient.d.ts.map +0 -1
- package/src/psm/types-ambient.js +0 -3
- package/src/vaultFactory/liquidation.d.ts +0 -25
- package/src/vaultFactory/liquidation.d.ts.map +0 -1
- package/src/vaultFactory/liquidation.js +0 -309
- package/src/vaultFactory/proceeds.d.ts +0 -35
- package/src/vaultFactory/proceeds.d.ts.map +0 -1
- package/src/vaultFactory/proceeds.js +0 -282
- package/src/vaultFactory/types-ambient.d.ts.map +0 -1
|
@@ -1,309 +0,0 @@
|
|
|
1
|
-
// @jessie-check
|
|
2
|
-
|
|
3
|
-
import { AmountMath } from '@agoric/ertp';
|
|
4
|
-
import { makeTracer } from '@agoric/internal';
|
|
5
|
-
import { observeIteration, subscribeEach } from '@agoric/notifier';
|
|
6
|
-
import { makeScalarMapStore } from '@agoric/store';
|
|
7
|
-
import { TimeMath } from '@agoric/time';
|
|
8
|
-
import { E } from '@endo/eventual-send';
|
|
9
|
-
|
|
10
|
-
import { AUCTION_START_DELAY, PRICE_LOCK_PERIOD } from '../auction/params.js';
|
|
11
|
-
import { makeCancelTokenMaker } from '../auction/util.js';
|
|
12
|
-
|
|
13
|
-
const trace = makeTracer('LIQ');
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* @import {MapStore, SetStore} from '@agoric/store';
|
|
17
|
-
* @import {RelativeTimeRecord, TimerService, TimerWaker} from '@agoric/time';
|
|
18
|
-
* @import {PriceQuote} from '@agoric/zoe/tools/types.js';
|
|
19
|
-
*/
|
|
20
|
-
|
|
21
|
-
const makeCancelToken = makeCancelTokenMaker('liq');
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* This will normally be set. If the schedule goes sideways, we'll unschedule
|
|
25
|
-
* all events and unset it. When auction params are changed, we'll restart the
|
|
26
|
-
* schedule
|
|
27
|
-
*
|
|
28
|
-
* @type {object | undefined}
|
|
29
|
-
*/
|
|
30
|
-
let cancelToken = makeCancelToken();
|
|
31
|
-
|
|
32
|
-
const waitForRepair = () => {
|
|
33
|
-
// the params observer will setWakeup to resume.
|
|
34
|
-
console.warn(
|
|
35
|
-
'🛠️ No wake for reschedule. Repair by resetting auction params.',
|
|
36
|
-
);
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
// Generally, canceling wakups has to be followed by setting up new ones but
|
|
40
|
-
// not in the case of pausing wakeups. We do that in the event of invalid
|
|
41
|
-
// schedule params. When they are repaired by governance, the wakers resume.
|
|
42
|
-
/** @param {ERef<TimerService>} timer */
|
|
43
|
-
const cancelWakeups = timer => {
|
|
44
|
-
if (cancelToken) {
|
|
45
|
-
void E(timer).cancel(cancelToken);
|
|
46
|
-
}
|
|
47
|
-
cancelToken = undefined;
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Schedule wakeups for the _next_ auction round.
|
|
52
|
-
*
|
|
53
|
-
* In practice, there are these cases to handle (with N as "live" and N+1 is
|
|
54
|
-
* "next"):
|
|
55
|
-
*
|
|
56
|
-
* | when (now within the range) | what |
|
|
57
|
-
* | ------------------------------- | ---------------------------------------- |
|
|
58
|
-
* | [start N, nominalStart N+1] | good: schedule normally the three wakers |
|
|
59
|
-
* | (nominalStart N+1, endTime N+1] | recover: skip round N+1 and schedule N+2 |
|
|
60
|
-
* | (endTime N+1, ∞) | give up: wait for repair by governance |
|
|
61
|
-
*
|
|
62
|
-
* @param {object} opts
|
|
63
|
-
* @param {ERef<TimerService>} opts.timer
|
|
64
|
-
* @param {TimerWaker} opts.priceLockWaker
|
|
65
|
-
* @param {TimerWaker} opts.liquidationWaker
|
|
66
|
-
* @param {TimerWaker} opts.reschedulerWaker
|
|
67
|
-
* @param {import('../auction/scheduler.js').Schedule} opts.nextAuctionSchedule
|
|
68
|
-
* @param {import('@agoric/time').TimestampRecord} opts.now
|
|
69
|
-
* @param {ParamStateRecord} opts.params
|
|
70
|
-
* @returns {void}
|
|
71
|
-
*/
|
|
72
|
-
const setWakeups = ({
|
|
73
|
-
nextAuctionSchedule,
|
|
74
|
-
now,
|
|
75
|
-
timer,
|
|
76
|
-
reschedulerWaker,
|
|
77
|
-
liquidationWaker,
|
|
78
|
-
priceLockWaker,
|
|
79
|
-
params,
|
|
80
|
-
}) => {
|
|
81
|
-
const { startTime, endTime } = nextAuctionSchedule;
|
|
82
|
-
|
|
83
|
-
/** @type {RelativeTimeRecord} */
|
|
84
|
-
// @ts-expect-error Casting
|
|
85
|
-
// eslint-disable-next-line no-restricted-syntax -- https://github.com/Agoric/eslint-config-jessie/issues/33
|
|
86
|
-
const priceLockPeriod = params[PRICE_LOCK_PERIOD].value;
|
|
87
|
-
/** @type {RelativeTimeRecord} */
|
|
88
|
-
// @ts-expect-error Casting
|
|
89
|
-
// eslint-disable-next-line no-restricted-syntax -- https://github.com/Agoric/eslint-config-jessie/issues/33
|
|
90
|
-
const auctionStartDelay = params[AUCTION_START_DELAY].value;
|
|
91
|
-
|
|
92
|
-
// nominal is the declared start time, but the actual auctioning begins after auctionStartDelay
|
|
93
|
-
const nominalStart = TimeMath.subtractAbsRel(startTime, auctionStartDelay);
|
|
94
|
-
|
|
95
|
-
// Is there a problem (case 2 or 3)?
|
|
96
|
-
// setWakeupsForNextAuction is supposed to be called just after an auction
|
|
97
|
-
// started. If we're late but there's still time for the nominal start, then
|
|
98
|
-
// we'll proceed. Reschedule for the next round if that's still in the future.
|
|
99
|
-
// Otherwise, wait for governance params to change.
|
|
100
|
-
if (TimeMath.compareAbs(now, nominalStart) > 0) {
|
|
101
|
-
// nominalStart is past, so cancel timers and plan to recover
|
|
102
|
-
cancelWakeups(timer);
|
|
103
|
-
|
|
104
|
-
if (TimeMath.compareAbs(now, endTime) < 0) {
|
|
105
|
-
// We're currently scheduling the N+1 (where N is live), but we need to skip it.
|
|
106
|
-
// So wake up for the N+2 round's startTime
|
|
107
|
-
const afterNextStartTime = TimeMath.addAbsRel(endTime, 1n);
|
|
108
|
-
trace(
|
|
109
|
-
'CASE 2: endTime is in the future or now so reschedule waking to startTime of the following round',
|
|
110
|
-
afterNextStartTime,
|
|
111
|
-
);
|
|
112
|
-
void E(timer).setWakeup(afterNextStartTime, reschedulerWaker);
|
|
113
|
-
} else {
|
|
114
|
-
trace('CASE 3: endTime is past; wait for repair');
|
|
115
|
-
waitForRepair();
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
return;
|
|
119
|
-
}
|
|
120
|
-
trace('CASE 1: nominalStart is now or in the future');
|
|
121
|
-
|
|
122
|
-
cancelToken = cancelToken || makeCancelToken();
|
|
123
|
-
const priceLockWakeTime = TimeMath.subtractAbsRel(
|
|
124
|
-
nominalStart,
|
|
125
|
-
priceLockPeriod,
|
|
126
|
-
);
|
|
127
|
-
const a = t => TimeMath.absValue(t);
|
|
128
|
-
trace('scheduling ', a(priceLockWakeTime), a(nominalStart), a(startTime));
|
|
129
|
-
void E(timer).setWakeup(priceLockWakeTime, priceLockWaker, cancelToken);
|
|
130
|
-
void E(timer).setWakeup(nominalStart, liquidationWaker, cancelToken);
|
|
131
|
-
// Call setWakeupsForNextAuction again one tick after nominalStart
|
|
132
|
-
const afterStart = TimeMath.addAbsRel(startTime, 1n);
|
|
133
|
-
void E(timer).setWakeup(afterStart, reschedulerWaker, cancelToken);
|
|
134
|
-
};
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* Schedule wakeups for the _next_ auction round.
|
|
138
|
-
*
|
|
139
|
-
* Called by vaultDirector's resetWakeupsForNextAuction at start() and every
|
|
140
|
-
* time there's a "reschedule" wakeup.
|
|
141
|
-
*
|
|
142
|
-
* @param {ERef<import('../auction/auctioneer.js').AuctioneerPublicFacet>} auctioneerPublicFacet
|
|
143
|
-
* @param {ERef<TimerService>} timer
|
|
144
|
-
* @param {TimerWaker} priceLockWaker
|
|
145
|
-
* @param {TimerWaker} liquidationWaker
|
|
146
|
-
* @param {TimerWaker} reschedulerWaker
|
|
147
|
-
* @returns {Promise<void>}
|
|
148
|
-
*/
|
|
149
|
-
export const setWakeupsForNextAuction = async (
|
|
150
|
-
auctioneerPublicFacet,
|
|
151
|
-
timer,
|
|
152
|
-
priceLockWaker,
|
|
153
|
-
liquidationWaker,
|
|
154
|
-
reschedulerWaker,
|
|
155
|
-
) => {
|
|
156
|
-
const [{ nextAuctionSchedule }, params, now] = await Promise.all([
|
|
157
|
-
E(auctioneerPublicFacet).getSchedules(),
|
|
158
|
-
E(auctioneerPublicFacet).getGovernedParams(),
|
|
159
|
-
E(timer).getCurrentTimestamp(),
|
|
160
|
-
]);
|
|
161
|
-
|
|
162
|
-
trace(
|
|
163
|
-
'setWakeupsForNextAuction at',
|
|
164
|
-
now.absValue,
|
|
165
|
-
'with',
|
|
166
|
-
nextAuctionSchedule,
|
|
167
|
-
);
|
|
168
|
-
if (!nextAuctionSchedule) {
|
|
169
|
-
// There should always be a nextAuctionSchedule. If there isn't, give up for now.
|
|
170
|
-
cancelWakeups(timer);
|
|
171
|
-
waitForRepair();
|
|
172
|
-
return;
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
setWakeups({
|
|
176
|
-
nextAuctionSchedule,
|
|
177
|
-
now,
|
|
178
|
-
timer,
|
|
179
|
-
reschedulerWaker,
|
|
180
|
-
liquidationWaker,
|
|
181
|
-
priceLockWaker,
|
|
182
|
-
params,
|
|
183
|
-
});
|
|
184
|
-
};
|
|
185
|
-
harden(setWakeupsForNextAuction);
|
|
186
|
-
|
|
187
|
-
/**
|
|
188
|
-
* @param {Amount<'nat'>} debt
|
|
189
|
-
* @param {Amount<'nat'>} minted
|
|
190
|
-
* @returns {{ overage: Amount<'nat'>; shortfall: Amount<'nat'> }}
|
|
191
|
-
*/
|
|
192
|
-
export const liquidationResults = (debt, minted) => {
|
|
193
|
-
if (AmountMath.isEmpty(minted)) {
|
|
194
|
-
return { overage: minted, shortfall: debt };
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
const [overage, shortfall] = AmountMath.isGTE(debt, minted)
|
|
198
|
-
? [AmountMath.makeEmptyFromAmount(debt), AmountMath.subtract(debt, minted)]
|
|
199
|
-
: [AmountMath.subtract(minted, debt), AmountMath.makeEmptyFromAmount(debt)];
|
|
200
|
-
|
|
201
|
-
return { overage, shortfall };
|
|
202
|
-
};
|
|
203
|
-
harden(liquidationResults);
|
|
204
|
-
|
|
205
|
-
/**
|
|
206
|
-
* Watch governed params for change
|
|
207
|
-
*
|
|
208
|
-
* @param {ERef<import('../auction/auctioneer.js').AuctioneerPublicFacet>} auctioneerPublicFacet
|
|
209
|
-
* @param {ERef<TimerService>} timer
|
|
210
|
-
* @param {TimerWaker} reschedulerWaker
|
|
211
|
-
* @returns {void}
|
|
212
|
-
*/
|
|
213
|
-
export const watchForGovernanceChange = (
|
|
214
|
-
auctioneerPublicFacet,
|
|
215
|
-
timer,
|
|
216
|
-
reschedulerWaker,
|
|
217
|
-
) => {
|
|
218
|
-
void E.when(E(timer).getCurrentTimestamp(), now =>
|
|
219
|
-
// make one observer that will usually ignore the update.
|
|
220
|
-
observeIteration(
|
|
221
|
-
subscribeEach(E(auctioneerPublicFacet).getSubscription()),
|
|
222
|
-
harden({
|
|
223
|
-
async updateState(_newState) {
|
|
224
|
-
if (!cancelToken) {
|
|
225
|
-
cancelToken = makeCancelToken();
|
|
226
|
-
void E(timer).setWakeup(
|
|
227
|
-
// bump one tick to prevent an infinite loop
|
|
228
|
-
TimeMath.addAbsRel(now, 1n),
|
|
229
|
-
reschedulerWaker,
|
|
230
|
-
cancelToken,
|
|
231
|
-
);
|
|
232
|
-
}
|
|
233
|
-
},
|
|
234
|
-
}),
|
|
235
|
-
),
|
|
236
|
-
);
|
|
237
|
-
};
|
|
238
|
-
|
|
239
|
-
/**
|
|
240
|
-
* @param {ZCF} zcf
|
|
241
|
-
* @param {object} collateralizationDetails
|
|
242
|
-
* @param {PriceQuote} collateralizationDetails.quote
|
|
243
|
-
* @param {Ratio} collateralizationDetails.interest
|
|
244
|
-
* @param {Ratio} collateralizationDetails.margin
|
|
245
|
-
* @param {ReturnType<
|
|
246
|
-
* typeof import('./prioritizedVaults.js').makePrioritizedVaults
|
|
247
|
-
* >} prioritizedVaults
|
|
248
|
-
* @param {SetStore<Vault>} liquidatingVaults
|
|
249
|
-
* @param {Brand<'nat'>} debtBrand
|
|
250
|
-
* @param {Brand<'nat'>} collateralBrand
|
|
251
|
-
* @returns {{
|
|
252
|
-
* vaultData: MapStore<
|
|
253
|
-
* Vault,
|
|
254
|
-
* { collateralAmount: Amount<'nat'>; debtAmount: Amount<'nat'> }
|
|
255
|
-
* >;
|
|
256
|
-
* totalDebt: Amount<'nat'>;
|
|
257
|
-
* totalCollateral: Amount<'nat'>;
|
|
258
|
-
* liqSeat: ZCFSeat;
|
|
259
|
-
* }}
|
|
260
|
-
*/
|
|
261
|
-
export const getLiquidatableVaults = (
|
|
262
|
-
zcf,
|
|
263
|
-
collateralizationDetails,
|
|
264
|
-
prioritizedVaults,
|
|
265
|
-
liquidatingVaults,
|
|
266
|
-
debtBrand,
|
|
267
|
-
collateralBrand,
|
|
268
|
-
) => {
|
|
269
|
-
const vaultsToLiquidate = prioritizedVaults.removeVaultsBelow(
|
|
270
|
-
collateralizationDetails,
|
|
271
|
-
);
|
|
272
|
-
/**
|
|
273
|
-
* @type {MapStore<
|
|
274
|
-
* Vault,
|
|
275
|
-
* { collateralAmount: Amount<'nat'>; debtAmount: Amount<'nat'> }
|
|
276
|
-
* >}
|
|
277
|
-
*/
|
|
278
|
-
const vaultData = makeScalarMapStore();
|
|
279
|
-
|
|
280
|
-
const { zcfSeat: liqSeat } = zcf.makeEmptySeatKit();
|
|
281
|
-
let totalDebt = AmountMath.makeEmpty(debtBrand);
|
|
282
|
-
let totalCollateral = AmountMath.makeEmpty(collateralBrand);
|
|
283
|
-
/** @type {TransferPart[]} */
|
|
284
|
-
const transfers = [];
|
|
285
|
-
|
|
286
|
-
for (const vault of vaultsToLiquidate.values()) {
|
|
287
|
-
vault.liquidating();
|
|
288
|
-
liquidatingVaults.add(vault);
|
|
289
|
-
|
|
290
|
-
const collateralAmount = vault.getCollateralAmount();
|
|
291
|
-
totalCollateral = AmountMath.add(totalCollateral, collateralAmount);
|
|
292
|
-
|
|
293
|
-
const debtAmount = vault.getCurrentDebt();
|
|
294
|
-
totalDebt = AmountMath.add(totalDebt, debtAmount);
|
|
295
|
-
transfers.push([
|
|
296
|
-
vault.getVaultSeat(),
|
|
297
|
-
liqSeat,
|
|
298
|
-
{ Collateral: collateralAmount },
|
|
299
|
-
]);
|
|
300
|
-
vaultData.init(vault, { collateralAmount, debtAmount });
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
if (transfers.length > 0) {
|
|
304
|
-
zcf.atomicRearrange(harden(transfers));
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
return { vaultData, totalDebt, totalCollateral, liqSeat };
|
|
308
|
-
};
|
|
309
|
-
harden(getLiquidatableVaults);
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
export function calculateDistributionPlan({ proceeds, totalDebt, totalCollateral, oraclePriceAtStart, vaultsBalances, penaltyRate, }: {
|
|
2
|
-
proceeds: AmountKeywordRecord;
|
|
3
|
-
totalDebt: Amount<"nat">;
|
|
4
|
-
totalCollateral: Amount<"nat">;
|
|
5
|
-
oraclePriceAtStart: PriceDescription;
|
|
6
|
-
vaultsBalances: VaultBalances[];
|
|
7
|
-
penaltyRate: Ratio;
|
|
8
|
-
}): DistributionPlan;
|
|
9
|
-
/**
|
|
10
|
-
* The plan to execute for distributing proceeds of a liquidation.
|
|
11
|
-
*
|
|
12
|
-
* Vaults are referenced by index in the list sent to the calculator.
|
|
13
|
-
*/
|
|
14
|
-
export type DistributionPlan = {
|
|
15
|
-
overage: Amount<"nat">;
|
|
16
|
-
shortfallToReserve: Amount<"nat">;
|
|
17
|
-
collateralForReserve: Amount<"nat">;
|
|
18
|
-
actualCollateralSold: Amount<"nat">;
|
|
19
|
-
collateralSold: Amount<"nat">;
|
|
20
|
-
collatRemaining: Amount<"nat">;
|
|
21
|
-
debtToBurn: Amount<"nat">;
|
|
22
|
-
mintedForReserve: Amount<"nat">;
|
|
23
|
-
mintedProceeds: Amount<"nat">;
|
|
24
|
-
phantomDebt: Amount<"nat">;
|
|
25
|
-
totalPenalty: Amount<"nat">;
|
|
26
|
-
transfersToVault: [number, AmountKeywordRecord][];
|
|
27
|
-
vaultsToReinstate: number[];
|
|
28
|
-
};
|
|
29
|
-
export type VaultBalances = {
|
|
30
|
-
collateral: Amount<"nat">;
|
|
31
|
-
presaleDebt: Amount<"nat">;
|
|
32
|
-
currentDebt: Amount<"nat">;
|
|
33
|
-
};
|
|
34
|
-
import type { PriceDescription } from '@agoric/zoe/tools/types.js';
|
|
35
|
-
//# sourceMappingURL=proceeds.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"proceeds.d.ts","sourceRoot":"","sources":["proceeds.js"],"names":[],"mappings":"AA4DO,sIATJ;IAAoC,QAAQ,EAApC,mBAAmB;IACG,SAAS,EAA/B,MAAM,CAAC,KAAK,CAAC;IACS,eAAe,EAArC,MAAM,CAAC,KAAK,CAAC;IACY,kBAAkB,EAA3C,gBAAgB;IACQ,cAAc,EAAtC,aAAa,EAAE;IAED,WAAW,EAAzB,KAAK;CACb,GAAU,gBAAgB,CA8N5B;;;;;;+BA1QY;IACR,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;IACvB,kBAAkB,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;IAClC,oBAAoB,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;IACpC,oBAAoB,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;IACpC,cAAc,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;IAC9B,eAAe,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;IAC/B,UAAU,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;IAC1B,gBAAgB,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;IAChC,cAAc,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;IAC9B,WAAW,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;IAC3B,YAAY,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;IAC5B,gBAAgB,EAAE,CAAC,MAAM,EAAE,mBAAmB,CAAC,EAAE,CAAC;IAClD,iBAAiB,EAAE,MAAM,EAAE,CAAC;CAC7B;4BAOS;IACR,UAAU,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;IAC3B,WAAW,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;CAC5B;sCA5B0F,4BAA4B"}
|
|
@@ -1,282 +0,0 @@
|
|
|
1
|
-
import { AmountMath } from '@agoric/ertp';
|
|
2
|
-
import {
|
|
3
|
-
ceilDivideBy,
|
|
4
|
-
ceilMultiplyBy,
|
|
5
|
-
floorMultiplyBy,
|
|
6
|
-
makeRatioFromAmounts,
|
|
7
|
-
multiplyRatios,
|
|
8
|
-
} from '@agoric/zoe/src/contractSupport/index.js';
|
|
9
|
-
import { quoteAsRatio, subtractToEmpty } from '../contractSupport.js';
|
|
10
|
-
import { liquidationResults } from './liquidation.js';
|
|
11
|
-
|
|
12
|
-
/** @import {PriceAuthority, PriceDescription, PriceQuote, PriceQuoteValue, PriceQuery,} from '@agoric/zoe/tools/types.js'; */
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* @typedef {{
|
|
16
|
-
* overage: Amount<'nat'>;
|
|
17
|
-
* shortfallToReserve: Amount<'nat'>;
|
|
18
|
-
* collateralForReserve: Amount<'nat'>;
|
|
19
|
-
* actualCollateralSold: Amount<'nat'>;
|
|
20
|
-
* collateralSold: Amount<'nat'>;
|
|
21
|
-
* collatRemaining: Amount<'nat'>;
|
|
22
|
-
* debtToBurn: Amount<'nat'>;
|
|
23
|
-
* mintedForReserve: Amount<'nat'>;
|
|
24
|
-
* mintedProceeds: Amount<'nat'>;
|
|
25
|
-
* phantomDebt: Amount<'nat'>;
|
|
26
|
-
* totalPenalty: Amount<'nat'>;
|
|
27
|
-
* transfersToVault: [number, AmountKeywordRecord][];
|
|
28
|
-
* vaultsToReinstate: number[];
|
|
29
|
-
* }} DistributionPlan
|
|
30
|
-
* The plan to execute for distributing proceeds of a liquidation.
|
|
31
|
-
*
|
|
32
|
-
* Vaults are referenced by index in the list sent to the calculator.
|
|
33
|
-
*/
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* @typedef {{
|
|
37
|
-
* collateral: Amount<'nat'>;
|
|
38
|
-
* presaleDebt: Amount<'nat'>;
|
|
39
|
-
* currentDebt: Amount<'nat'>;
|
|
40
|
-
* }} VaultBalances
|
|
41
|
-
*/
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Liquidation.md describes how to process liquidation proceeds.
|
|
45
|
-
*
|
|
46
|
-
* This function is complex and may fail. To defend against this possibility, it
|
|
47
|
-
* starts with a base plan and updates it. The updating is the complex portion
|
|
48
|
-
* and is wrapped in a try/catch. If at any point the plan revising fails, the
|
|
49
|
-
* plan is returned as is.
|
|
50
|
-
*
|
|
51
|
-
* @param {object} inputs
|
|
52
|
-
* @param {AmountKeywordRecord} inputs.proceeds
|
|
53
|
-
* @param {Amount<'nat'>} inputs.totalDebt
|
|
54
|
-
* @param {Amount<'nat'>} inputs.totalCollateral
|
|
55
|
-
* @param {PriceDescription} inputs.oraclePriceAtStart
|
|
56
|
-
* @param {VaultBalances[]} inputs.vaultsBalances ordered best to worst
|
|
57
|
-
* collateralized
|
|
58
|
-
* @param {Ratio} inputs.penaltyRate
|
|
59
|
-
* @returns {DistributionPlan}
|
|
60
|
-
*/
|
|
61
|
-
export const calculateDistributionPlan = ({
|
|
62
|
-
proceeds,
|
|
63
|
-
totalDebt,
|
|
64
|
-
totalCollateral,
|
|
65
|
-
oraclePriceAtStart,
|
|
66
|
-
vaultsBalances,
|
|
67
|
-
penaltyRate,
|
|
68
|
-
}) => {
|
|
69
|
-
const emptyCollateral = AmountMath.makeEmptyFromAmount(totalCollateral);
|
|
70
|
-
const emptyMinted = AmountMath.makeEmptyFromAmount(totalDebt);
|
|
71
|
-
|
|
72
|
-
const { Collateral: collateralProceeds } = proceeds;
|
|
73
|
-
/** @type {Amount<'nat'>} */
|
|
74
|
-
const collateralSold = AmountMath.subtract(
|
|
75
|
-
totalCollateral,
|
|
76
|
-
collateralProceeds,
|
|
77
|
-
);
|
|
78
|
-
|
|
79
|
-
const mintedProceeds = proceeds.Minted || emptyMinted;
|
|
80
|
-
const accounting = liquidationResults(totalDebt, mintedProceeds);
|
|
81
|
-
|
|
82
|
-
// charged in collateral
|
|
83
|
-
const totalPenalty = ceilMultiplyBy(
|
|
84
|
-
totalDebt,
|
|
85
|
-
multiplyRatios(penaltyRate, quoteAsRatio(oraclePriceAtStart)),
|
|
86
|
-
);
|
|
87
|
-
|
|
88
|
-
const debtPortion = makeRatioFromAmounts(totalPenalty, totalDebt);
|
|
89
|
-
|
|
90
|
-
// We mutate the plan so that at any point if there's an error the plan can be returned and executed.
|
|
91
|
-
// IOW the plan must always be in a valid state, though perhaps incomplete.
|
|
92
|
-
/** @type {DistributionPlan} */
|
|
93
|
-
const plan = {
|
|
94
|
-
overage: accounting.overage,
|
|
95
|
-
shortfallToReserve: accounting.shortfall,
|
|
96
|
-
collateralForReserve: emptyCollateral,
|
|
97
|
-
actualCollateralSold: emptyCollateral,
|
|
98
|
-
collateralSold,
|
|
99
|
-
collatRemaining: emptyCollateral,
|
|
100
|
-
debtToBurn: emptyMinted,
|
|
101
|
-
mintedForReserve: emptyMinted,
|
|
102
|
-
mintedProceeds,
|
|
103
|
-
phantomDebt: emptyMinted,
|
|
104
|
-
transfersToVault: [],
|
|
105
|
-
vaultsToReinstate: [],
|
|
106
|
-
totalPenalty,
|
|
107
|
-
};
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* If interest was charged between liquidating and liquidated, erase it.
|
|
111
|
-
*
|
|
112
|
-
* @param {VaultBalances} balances
|
|
113
|
-
*/
|
|
114
|
-
const updatePhantomDebt = ({ presaleDebt, currentDebt }) => {
|
|
115
|
-
if (AmountMath.isEqual(presaleDebt, currentDebt)) {
|
|
116
|
-
return;
|
|
117
|
-
}
|
|
118
|
-
const accrued = AmountMath.subtract(currentDebt, presaleDebt);
|
|
119
|
-
plan.phantomDebt = AmountMath.add(plan.phantomDebt, accrued);
|
|
120
|
-
};
|
|
121
|
-
|
|
122
|
-
const runFlow1 = () => {
|
|
123
|
-
// Flow #1: no shortfall
|
|
124
|
-
|
|
125
|
-
const distributableCollateral = subtractToEmpty(
|
|
126
|
-
collateralProceeds,
|
|
127
|
-
totalPenalty,
|
|
128
|
-
);
|
|
129
|
-
|
|
130
|
-
plan.debtToBurn = totalDebt;
|
|
131
|
-
plan.mintedForReserve = accounting.overage;
|
|
132
|
-
|
|
133
|
-
// return remaining funds to vaults before closing
|
|
134
|
-
|
|
135
|
-
let leftToStage = distributableCollateral;
|
|
136
|
-
const price = makeRatioFromAmounts(mintedProceeds, collateralSold);
|
|
137
|
-
|
|
138
|
-
// iterate from best to worst, returning collateral until it has
|
|
139
|
-
// been exhausted. Vaults after that get nothing.
|
|
140
|
-
for (const [vaultIndex, balances] of vaultsBalances.entries()) {
|
|
141
|
-
const { collateral: vCollat, presaleDebt } = balances;
|
|
142
|
-
updatePhantomDebt(balances);
|
|
143
|
-
|
|
144
|
-
// max return is vault value reduced by debt and penalty value
|
|
145
|
-
const debtCollat = ceilDivideBy(presaleDebt, price);
|
|
146
|
-
const penaltyCollat = ceilMultiplyBy(presaleDebt, debtPortion);
|
|
147
|
-
const lessCollat = AmountMath.add(debtCollat, penaltyCollat);
|
|
148
|
-
|
|
149
|
-
const maxCollat = subtractToEmpty(vCollat, lessCollat);
|
|
150
|
-
if (!AmountMath.isEmpty(leftToStage)) {
|
|
151
|
-
const collatReturn = AmountMath.min(leftToStage, maxCollat);
|
|
152
|
-
leftToStage = AmountMath.subtract(leftToStage, collatReturn);
|
|
153
|
-
plan.transfersToVault.push([vaultIndex, { Collateral: collatReturn }]);
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
const hasCollateralToDistribute = !AmountMath.isEmpty(
|
|
158
|
-
distributableCollateral,
|
|
159
|
-
);
|
|
160
|
-
plan.collateralForReserve = hasCollateralToDistribute
|
|
161
|
-
? AmountMath.add(leftToStage, totalPenalty)
|
|
162
|
-
: collateralProceeds;
|
|
163
|
-
};
|
|
164
|
-
|
|
165
|
-
// Flow 2a: all collateral was sold but debt was not covered
|
|
166
|
-
const runFlow2a = () => {
|
|
167
|
-
// charge penalty if proceeds are sufficient
|
|
168
|
-
const penaltyInMinted = ceilMultiplyBy(totalDebt, penaltyRate);
|
|
169
|
-
const recoveredDebt = AmountMath.min(
|
|
170
|
-
AmountMath.add(totalDebt, penaltyInMinted),
|
|
171
|
-
mintedProceeds,
|
|
172
|
-
);
|
|
173
|
-
|
|
174
|
-
plan.debtToBurn = recoveredDebt;
|
|
175
|
-
|
|
176
|
-
const distributable = subtractToEmpty(mintedProceeds, recoveredDebt);
|
|
177
|
-
let mintedRemaining = distributable;
|
|
178
|
-
|
|
179
|
-
const vaultPortion = makeRatioFromAmounts(distributable, totalCollateral);
|
|
180
|
-
|
|
181
|
-
// iterate from best to worst returning remaining funds to vaults
|
|
182
|
-
for (const [vaultIndex, balances] of vaultsBalances.entries()) {
|
|
183
|
-
// from best to worst, return minted above penalty if any remains
|
|
184
|
-
const vaultShare = floorMultiplyBy(balances.collateral, vaultPortion);
|
|
185
|
-
updatePhantomDebt(balances);
|
|
186
|
-
|
|
187
|
-
if (!AmountMath.isEmpty(mintedRemaining)) {
|
|
188
|
-
const mintedToReturn = AmountMath.min(mintedRemaining, vaultShare);
|
|
189
|
-
mintedRemaining = AmountMath.subtract(mintedRemaining, mintedToReturn);
|
|
190
|
-
plan.transfersToVault.push([vaultIndex, { Minted: mintedToReturn }]);
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
};
|
|
194
|
-
|
|
195
|
-
// Flow 2b: collateral remains but debt was not covered
|
|
196
|
-
const runFlow2b = () => {
|
|
197
|
-
plan.debtToBurn = totalDebt;
|
|
198
|
-
plan.mintedForReserve = accounting.overage;
|
|
199
|
-
|
|
200
|
-
// reconstitute vaults until collateral is insufficient
|
|
201
|
-
let reconstituteVaults = AmountMath.isGTE(collateralProceeds, totalPenalty);
|
|
202
|
-
|
|
203
|
-
// charge penalty if proceeds are sufficient
|
|
204
|
-
const distributableCollateral = subtractToEmpty(
|
|
205
|
-
collateralProceeds,
|
|
206
|
-
totalPenalty,
|
|
207
|
-
);
|
|
208
|
-
|
|
209
|
-
plan.collatRemaining = distributableCollateral;
|
|
210
|
-
|
|
211
|
-
let shortfallToReserve = accounting.shortfall;
|
|
212
|
-
const reduceCollateral = amount =>
|
|
213
|
-
(plan.actualCollateralSold = AmountMath.add(
|
|
214
|
-
plan.actualCollateralSold,
|
|
215
|
-
amount,
|
|
216
|
-
));
|
|
217
|
-
|
|
218
|
-
// iterate from best to worst attempting to reconstitute, by
|
|
219
|
-
// returning remaining funds to vaults
|
|
220
|
-
for (const [vaultIndex, balances] of vaultsBalances.entries()) {
|
|
221
|
-
const { collateral: vCollat, presaleDebt } = balances;
|
|
222
|
-
|
|
223
|
-
// according to #7123, Collateral for penalty =
|
|
224
|
-
// total liquidation penalty * vault debt / total debt
|
|
225
|
-
const vaultPenalty = ceilMultiplyBy(presaleDebt, debtPortion);
|
|
226
|
-
const collatPostPenalty = subtractToEmpty(vCollat, vaultPenalty);
|
|
227
|
-
const vaultDebt = floorMultiplyBy(presaleDebt, debtPortion);
|
|
228
|
-
|
|
229
|
-
// Should we continue reconstituting vaults?
|
|
230
|
-
reconstituteVaults =
|
|
231
|
-
reconstituteVaults &&
|
|
232
|
-
!AmountMath.isEmpty(collatPostPenalty) &&
|
|
233
|
-
AmountMath.isGTE(plan.collatRemaining, collatPostPenalty) &&
|
|
234
|
-
AmountMath.isGTE(totalDebt, presaleDebt);
|
|
235
|
-
|
|
236
|
-
if (reconstituteVaults) {
|
|
237
|
-
plan.collatRemaining = AmountMath.subtract(
|
|
238
|
-
plan.collatRemaining,
|
|
239
|
-
collatPostPenalty,
|
|
240
|
-
);
|
|
241
|
-
shortfallToReserve = subtractToEmpty(shortfallToReserve, presaleDebt);
|
|
242
|
-
// must reinstate after atomicRearrange(), so we record them.
|
|
243
|
-
plan.vaultsToReinstate.push(vaultIndex);
|
|
244
|
-
reduceCollateral(vaultDebt);
|
|
245
|
-
plan.transfersToVault.push([
|
|
246
|
-
vaultIndex,
|
|
247
|
-
{ Collateral: collatPostPenalty },
|
|
248
|
-
]);
|
|
249
|
-
} else {
|
|
250
|
-
updatePhantomDebt(balances);
|
|
251
|
-
|
|
252
|
-
reduceCollateral(vCollat);
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
plan.collateralForReserve = AmountMath.add(
|
|
257
|
-
plan.collatRemaining,
|
|
258
|
-
totalPenalty,
|
|
259
|
-
);
|
|
260
|
-
|
|
261
|
-
plan.shortfallToReserve = shortfallToReserve;
|
|
262
|
-
};
|
|
263
|
-
|
|
264
|
-
try {
|
|
265
|
-
if (AmountMath.isEmpty(accounting.shortfall)) {
|
|
266
|
-
// Flow #1: no shortfall
|
|
267
|
-
runFlow1();
|
|
268
|
-
} else if (AmountMath.isEmpty(collateralProceeds)) {
|
|
269
|
-
// Flow 2a: all collateral was sold but debt was not covered
|
|
270
|
-
runFlow2a();
|
|
271
|
-
} else {
|
|
272
|
-
// Flow #2b: There's unsold collateral; some vaults may be reinstated.
|
|
273
|
-
runFlow2b();
|
|
274
|
-
}
|
|
275
|
-
} catch (err) {
|
|
276
|
-
console.error('🚨 Failure running distribution flow:', err);
|
|
277
|
-
// continue to return `plan` in the state that was reached
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
return harden(plan);
|
|
281
|
-
};
|
|
282
|
-
harden(calculateDistributionPlan);
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types-ambient.d.ts","sourceRoot":"","sources":["types-ambient.js"],"names":[],"mappings":"+BAGa,OAAO,mBAAmB,EAAE,oBAAoB,CAAC,aAAa,CAAC;;mBAe9D,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,KAAK,MAAM;wBACxC,MAAM,UAAU;;;;;;;uBAKhB,KAAK;;;;;wBAEL,KAAK;;;;;kBAEL,KAAK;;;;;aAEL,KAAK;eAEL,MAAM,CAAC,KAAK,CAAC;;;;;;;uCAOhB,MAAM,qBACN,OAAO,UACP,uBAAuB,KACrB,OAAO,CAAC,YAAY,CAAC;;kBAKpB,YAAY;yBACZ,MAAM,OAAO,aAAa,EAAE,UAAU;+BACtC,MAAM,OAAO,CAAC,UAAU,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;0BACxC,MAAM,OAAO,cAAc,EAAE,UAAU;wBACvC,MAAM,OAAO,cAAc,EAAE,UAAU;;;;;;;;sCAQ1C,OAAO,UACP,MAAM,CAAC,KAAK,CAAC,OACb,MAAM,CAAC,KAAK,CAAC,aACb,YAAY,EAAE,KACZ,IAAI;;;;;yBAMN,MAAM,YACN,OAAO,KACL,IAAI;;0BAKH,MAAM,KAAK;gBACX,MAAM,KAAK;wBACX,MAAM,OAAO,CAAC,OAAO,4BAA4B,EAAE,UAAU,CAAC;;;;;qBAC9D,MAAM,KAAK;;;;;uBAEX,MAAM,YAAY;;;;;wBAElB,MAAM,YAAY;;eAIlB,MAAM;;;;;oBAIN,YAAY;;;;qBACZ,YAAY;;;oBAKZ,MAAM,oBAAoB;kBAC1B,CACT,UAAU,EAAE,MAAM,EAClB,GAAG,EAAE,MAAM,KACR,OAAO,aAAa,EAAE,QAAQ;oBACxB,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,CAAC;;;6BAKrC,MAAM,OAAO,CACtB,UAAU,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;QAAC,WAAW,EAAE,KAAK,CAAA;KAAE,CAAC,CAC9D;;;0BAKU,SAAS;;;;cACT,QAAQ;;;;aACR,QAAQ;;8BAKX,UAAU,eACV,SAAS,KACP,UAAU;;;;;;eAKT,SAAS;;;;;;;8BAET,SAAS;;6BAMT;IAAE,GAAG,EAAE,gBAAgB,GAAG;QAAE,eAAe,EAAE,KAAK,CAAA;KAAE,CAAA;CAAE;uCApIhC,YAAY;2BACxB,YAAY;8BACT,eAAe;kCACX,mBAAmB;uCACd,mBAAmB;qDACL,4BAA4B;6CACpC,4BAA4B;2CAC9B,0BAA0B;+BACtC,cAAc;kCACX,cAAc"}
|