@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.
Files changed (140) hide show
  1. package/README.md +26 -20
  2. package/bundles/bundle-auctioneer-js-meta.json +722 -0
  3. package/bundles/bundle-auctioneer.js +1 -0
  4. package/bundles/bundle-econCommitteeCharter-js-meta.json +514 -0
  5. package/bundles/bundle-econCommitteeCharter.js +1 -0
  6. package/bundles/bundle-feeDistributor-js-meta.json +458 -0
  7. package/bundles/bundle-feeDistributor.js +1 -1
  8. package/bundles/bundle-fluxAggregatorKit-js-meta.json +674 -0
  9. package/bundles/bundle-fluxAggregatorKit.js +1 -0
  10. package/bundles/bundle-psm-js-meta.json +666 -0
  11. package/bundles/bundle-psm.js +1 -1
  12. package/bundles/bundle-reserve-js-meta.json +662 -0
  13. package/bundles/bundle-reserve.js +1 -1
  14. package/bundles/bundle-scaledPriceAuthority-js-meta.json +542 -0
  15. package/bundles/bundle-scaledPriceAuthority.js +1 -1
  16. package/bundles/bundle-vaultFactory-js-meta.json +786 -0
  17. package/bundles/bundle-vaultFactory.js +1 -1
  18. package/exported.js +0 -2
  19. package/package.json +34 -31
  20. package/scripts/add-collateral-core.js +14 -4
  21. package/scripts/build-bundles.js +9 -2
  22. package/scripts/deploy-contracts.js +1 -4
  23. package/scripts/init-core.js +20 -38
  24. package/scripts/invite-committee-core.js +1 -1
  25. package/scripts/manual-price-feed.js +2 -2
  26. package/scripts/price-feed-core.js +7 -6
  27. package/scripts/start-local-chain.sh +84 -0
  28. package/src/auction/auctionBook.js +755 -0
  29. package/src/auction/auctioneer.js +720 -0
  30. package/src/auction/offerBook.js +221 -0
  31. package/src/auction/params.js +174 -0
  32. package/src/auction/scheduleMath.js +167 -0
  33. package/src/auction/scheduler.js +370 -0
  34. package/src/auction/sortedOffers.js +136 -0
  35. package/src/auction/util.js +55 -0
  36. package/src/clientSupport.js +324 -0
  37. package/src/collectFees.js +8 -14
  38. package/src/contractSupport.js +24 -68
  39. package/src/econCommitteeCharter.js +161 -77
  40. package/src/feeDistributor.js +60 -20
  41. package/src/index.js +2 -0
  42. package/src/interest-math.js +1 -4
  43. package/src/interest.js +20 -13
  44. package/src/price/README.md +57 -0
  45. package/src/price/fluxAggregatorContract.js +190 -0
  46. package/src/price/fluxAggregatorKit.js +375 -0
  47. package/src/price/priceOracleKit.js +127 -0
  48. package/src/price/roundsManager.js +726 -0
  49. package/src/proposals/addAssetToVault.js +89 -94
  50. package/src/proposals/committee-proposal.js +141 -40
  51. package/src/proposals/core-proposal.js +100 -167
  52. package/src/proposals/econ-behaviors.js +320 -564
  53. package/src/proposals/price-feed-proposal.js +175 -78
  54. package/src/proposals/startEconCommittee.js +25 -12
  55. package/src/proposals/startPSM.js +231 -211
  56. package/src/proposals/utils.js +31 -17
  57. package/src/psm/README.md +71 -0
  58. package/src/psm/psm.js +272 -160
  59. package/src/psm/types.js +2 -0
  60. package/src/reserve/assetReserve.js +56 -413
  61. package/src/reserve/assetReserveKit.js +303 -0
  62. package/src/reserve/doc.md +1 -3
  63. package/src/reserve/params.js +2 -5
  64. package/src/typeGuards.js +13 -0
  65. package/src/vaultFactory/Liquidation.md +100 -0
  66. package/src/vaultFactory/burn.js +2 -1
  67. package/src/vaultFactory/liquidation.js +270 -108
  68. package/src/vaultFactory/math.js +95 -0
  69. package/src/vaultFactory/orderedVaultStore.js +0 -1
  70. package/src/vaultFactory/params.js +133 -112
  71. package/src/vaultFactory/prioritizedVaults.js +36 -79
  72. package/src/vaultFactory/storeUtils.js +67 -9
  73. package/src/vaultFactory/type-imports.js +2 -0
  74. package/src/vaultFactory/types.js +22 -26
  75. package/src/vaultFactory/vault.js +772 -709
  76. package/src/vaultFactory/vaultDirector.js +480 -483
  77. package/src/vaultFactory/vaultFactory.js +99 -60
  78. package/src/vaultFactory/vaultHolder.js +121 -95
  79. package/src/vaultFactory/vaultKit.js +39 -31
  80. package/src/vaultFactory/vaultManager.js +1249 -868
  81. package/bundles/bundle-amm-meta.js +0 -618
  82. package/bundles/bundle-amm.js +0 -1
  83. package/bundles/bundle-feeDistributor-meta.js +0 -346
  84. package/bundles/bundle-interchainPool-meta.js +0 -534
  85. package/bundles/bundle-interchainPool.js +0 -1
  86. package/bundles/bundle-liquidateIncrementally-meta.js +0 -442
  87. package/bundles/bundle-liquidateIncrementally.js +0 -1
  88. package/bundles/bundle-liquidateMinimum-meta.js +0 -442
  89. package/bundles/bundle-liquidateMinimum.js +0 -1
  90. package/bundles/bundle-psm-meta.js +0 -538
  91. package/bundles/bundle-psmCharter-meta.js +0 -418
  92. package/bundles/bundle-psmCharter.js +0 -1
  93. package/bundles/bundle-reserve-meta.js +0 -542
  94. package/bundles/bundle-scaledPriceAuthority-meta.js +0 -442
  95. package/bundles/bundle-stakeFactory-meta.js +0 -574
  96. package/bundles/bundle-stakeFactory.js +0 -1
  97. package/bundles/bundle-vaultFactory-meta.js +0 -598
  98. package/scripts/add-initial-liquidity.js +0 -180
  99. package/src/collect.js +0 -13
  100. package/src/interchainPool.js +0 -135
  101. package/src/makeTracer.js +0 -36
  102. package/src/my-lien.js +0 -85
  103. package/src/proposals/demoIssuers.js +0 -685
  104. package/src/proposals/sim-behaviors.js +0 -40
  105. package/src/psm/psmCharter.js +0 -139
  106. package/src/stakeFactory/README.md +0 -62
  107. package/src/stakeFactory/attestation.js +0 -267
  108. package/src/stakeFactory/attestationTool.js +0 -66
  109. package/src/stakeFactory/constants.js +0 -16
  110. package/src/stakeFactory/params.js +0 -31
  111. package/src/stakeFactory/stakeFactory.js +0 -236
  112. package/src/stakeFactory/stakeFactoryKit.js +0 -455
  113. package/src/stakeFactory/stakeFactoryManager.js +0 -296
  114. package/src/stakeFactory/types.js +0 -42
  115. package/src/vaultFactory/liquidateIncrementally.js +0 -350
  116. package/src/vaultFactory/liquidateMinimum.js +0 -100
  117. package/src/vpool-xyk-amm/AttackersGuide.md +0 -89
  118. package/src/vpool-xyk-amm/addLiquidity.js +0 -222
  119. package/src/vpool-xyk-amm/addPool.js +0 -197
  120. package/src/vpool-xyk-amm/constantProduct/AMM-Trade.jpeg +0 -0
  121. package/src/vpool-xyk-amm/constantProduct/README.md +0 -204
  122. package/src/vpool-xyk-amm/constantProduct/calcFees.js +0 -99
  123. package/src/vpool-xyk-amm/constantProduct/calcSwapPrices.js +0 -85
  124. package/src/vpool-xyk-amm/constantProduct/core.js +0 -153
  125. package/src/vpool-xyk-amm/constantProduct/defaults.js +0 -5
  126. package/src/vpool-xyk-amm/constantProduct/getXY.js +0 -52
  127. package/src/vpool-xyk-amm/constantProduct/internal-types.js +0 -116
  128. package/src/vpool-xyk-amm/constantProduct/invariants.js +0 -43
  129. package/src/vpool-xyk-amm/constantProduct/swap.js +0 -272
  130. package/src/vpool-xyk-amm/constantProduct/types.js +0 -32
  131. package/src/vpool-xyk-amm/doublePool.js +0 -194
  132. package/src/vpool-xyk-amm/estimate.js +0 -155
  133. package/src/vpool-xyk-amm/multipoolMarketMaker.js +0 -520
  134. package/src/vpool-xyk-amm/params.js +0 -61
  135. package/src/vpool-xyk-amm/pool.js +0 -396
  136. package/src/vpool-xyk-amm/priceAuthority.js +0 -94
  137. package/src/vpool-xyk-amm/removeLiquidity.js +0 -31
  138. package/src/vpool-xyk-amm/singlePool.js +0 -73
  139. package/src/vpool-xyk-amm/swap.js +0 -69
  140. package/src/vpool-xyk-amm/types.js +0 -154
@@ -1,236 +0,0 @@
1
- // @ts-check
2
- // @jessie-check
3
- import { AmountMath } from '@agoric/ertp';
4
- import { handleParamGovernance, ParamTypes } from '@agoric/governance';
5
- import { E, Far } from '@endo/far';
6
- import { makeMakeCollectFeesInvitation } from '../collectFees.js';
7
- import { makeAttestationFacets } from './attestation.js';
8
- import { ManagerKW as KW } from './constants.js';
9
- import { makeStakeFactoryKit } from './stakeFactoryKit.js';
10
- import { makeStakeFactoryManager } from './stakeFactoryManager.js';
11
-
12
- const { details: X } = assert;
13
- const { values } = Object;
14
-
15
- /**
16
- * Provide loans on the basis of staked assets that earn rewards.
17
- *
18
- * In addition to brands and issuers for `Staked`, `Minted`, and attestation,
19
- * terms of the contract include a periodic `InterestRate`
20
- * plus a `LoanFee` proportional to the amount borrowed, as well as
21
- * a `MintingRatio` of funds to (mint and) loan per unit of staked asset.
22
- * These terms are subject to change by the `Electorate`
23
- * and `electionManager` terms.
24
- *
25
- * @typedef {{
26
- * DebtLimit: 'amount',
27
- * MintingRatio: 'ratio',
28
- * InterestRate: 'ratio',
29
- * LoanFee: 'ratio',
30
- * }} StakeFactoryParams
31
- *
32
- * As in vaultFactory, `timerService` provides the periodic signal to
33
- * charge interest according to `chargingPeriod` and `recordingPeriod`.
34
- *
35
- * @typedef { GovernanceTerms<StakeFactoryParams> & {
36
- * timerService: TimerService,
37
- * chargingPeriod: bigint,
38
- * recordingPeriod: bigint,
39
- * lienAttestationName?: string,
40
- * }} StakeFactoryTerms
41
- *
42
- * The public facet provides access to invitations to get a loan
43
- * or to return an attestation in order to release a lien on staked assets.
44
- *
45
- * @typedef {{
46
- * makeLoanInvitation: () => Promise<Invitation>,
47
- * makeReturnAttInvitation: () => Promise<Invitation>,
48
- * }} StakeFactoryPublic
49
- *
50
- * To take out a loan, get an `AttestationMaker` for your address from
51
- * the creator of this contract, and use
52
- * `E(attMaker).makeAttestation(stakedAmount)` to take out a lien
53
- * and get a payment that attests to the lien. Provide the payment
54
- * in the `Attestation` keyword of an offer,
55
- * using `{ want: { Debt: amountWanted }}`.
56
- *
57
- * Then, using the invitationMakers pattern, use `AdjustBalances` to
58
- * pay down the loan or otherwise adjust the `Debt` and `Attestation`.
59
- *
60
- * Finally, `Close` the loan, providing `{ give: Debt: debtAmount }}`
61
- *
62
- * To start the contract, authorize minting assets by providing `feeMintAccess`
63
- * and provide access to the underlying staking infrastructure in `lienBridge`.
64
- *
65
- * @typedef {{
66
- * feeMintAccess: FeeMintAccess,
67
- * initialPoserInvitation: Invitation,
68
- * lienBridge: ERef<StakingAuthority>,
69
- * storageNode: StorageNode,
70
- * marshaller: Marshaller,
71
- * }} StakeFactoryPrivateArgs
72
- *
73
- * The creator facet can make an `AttestationMaker` for each account, which
74
- * authorizes placing a lien some of the staked assets in that account.
75
- * @typedef {{
76
- * provideAttestationMaker: (addr: string) => AttestationTool,
77
- * makeCollectFeesInvitation: () => Promise<Invitation>,
78
- * }} StakeFactoryCreator
79
- *
80
- * @type {ContractStartFn<StakeFactoryPublic, ERef<GovernedCreatorFacet<StakeFactoryCreator>>,
81
- * StakeFactoryTerms, StakeFactoryPrivateArgs>}
82
- */
83
- export const start = async (
84
- zcf,
85
- {
86
- feeMintAccess,
87
- initialPoserInvitation,
88
- lienBridge,
89
- storageNode,
90
- marshaller,
91
- },
92
- ) => {
93
- const {
94
- brands: { Stake: stakeBrand },
95
- timerService,
96
- chargingPeriod,
97
- recordingPeriod,
98
- } = zcf.getTerms();
99
- assert.typeof(chargingPeriod, 'bigint', 'chargingPeriod must be a bigint');
100
- assert.typeof(recordingPeriod, 'bigint', 'recordingPeriod must be a bigint');
101
- assert(storageNode && marshaller, 'missing storageNode or marshaller');
102
-
103
- /** @type {ZCFMint<'nat'>} */
104
- const debtMint = await zcf.registerFeeMint(KW.Debt, feeMintAccess);
105
- const { brand: debtBrand } = debtMint.getIssuerRecord();
106
-
107
- const att = await makeAttestationFacets(zcf, stakeBrand, lienBridge);
108
- const attestBrand = await E(att.publicFacet).getBrand();
109
-
110
- const { augmentPublicFacet, makeGovernorFacet, params } =
111
- await handleParamGovernance(
112
- zcf,
113
- initialPoserInvitation,
114
- {
115
- DebtLimit: ParamTypes.AMOUNT,
116
- InterestRate: ParamTypes.RATIO,
117
- LoanFee: ParamTypes.RATIO,
118
- MintingRatio: ParamTypes.RATIO,
119
- },
120
- storageNode,
121
- marshaller,
122
- );
123
-
124
- /** For temporary staging of newly minted tokens */
125
- const { zcfSeat: mintSeat } = zcf.makeEmptySeatKit();
126
- const { zcfSeat: rewardPoolSeat } = zcf.makeEmptySeatKit();
127
-
128
- /**
129
- * Let the manager add rewards to the rewardPoolSeat
130
- * without directly exposing the rewardPoolSeat to them.
131
- *
132
- * @type {MintAndReallocate}
133
- */
134
- const mintAndReallocate = (toMint, fee, seat, ...otherSeats) => {
135
- const kept = AmountMath.subtract(toMint, fee);
136
- debtMint.mintGains(harden({ [KW.Debt]: toMint }), mintSeat);
137
- try {
138
- rewardPoolSeat.incrementBy(
139
- mintSeat.decrementBy(harden({ [KW.Debt]: fee })),
140
- );
141
- seat.incrementBy(mintSeat.decrementBy(harden({ [KW.Debt]: kept })));
142
- zcf.reallocate(
143
- rewardPoolSeat,
144
- mintSeat,
145
- seat,
146
- ...otherSeats.filter(s => s.hasStagedAllocation()),
147
- );
148
- } catch (e) {
149
- mintSeat.clear();
150
- rewardPoolSeat.clear();
151
- // Make best efforts to burn the newly minted tokens, for hygiene.
152
- // That only relies on the internal mint, so it cannot fail without
153
- // there being much larger problems. There's no risk of tokens being
154
- // stolen here because the staging for them was already cleared.
155
- debtMint.burnLosses(harden({ [KW.Debt]: toMint }), mintSeat);
156
- throw e;
157
- } finally {
158
- assert(
159
- values(mintSeat.getCurrentAllocation()).every(a =>
160
- AmountMath.isEmpty(a),
161
- ),
162
- X`Stage should be empty of Debt`,
163
- );
164
- }
165
- // TODO add aggregate debt tracking at the vaultFactory level #4482
166
- // totalDebt = AmountMath.add(totalDebt, toMint);
167
- };
168
-
169
- const burnDebt = (toBurn, seat) => {
170
- debtMint.burnLosses(harden({ [KW.Debt]: toBurn }), seat);
171
- };
172
-
173
- const mintPowers = Far('mintPowers', {
174
- burnDebt,
175
- getGovernedParams: () => params, // XXX until governance support is durable
176
- mintAndReallocate,
177
- });
178
-
179
- const startTimeStamp = await E(timerService).getCurrentTimestamp();
180
- const { manager } = makeStakeFactoryManager(
181
- zcf,
182
- debtMint,
183
- harden({ Attestation: attestBrand, debt: debtBrand, Stake: stakeBrand }),
184
- mintPowers,
185
- { timerService, chargingPeriod, recordingPeriod, startTimeStamp },
186
- );
187
-
188
- /**
189
- * @param {ZCFSeat} seat
190
- */
191
- const offerHandler = seat => {
192
- const { helper, pot } = makeStakeFactoryKit(zcf, seat, manager);
193
-
194
- return harden({
195
- publicSubscribers: {
196
- // XXX should come from manager directly https://github.com/Agoric/agoric-sdk/issues/5814
197
- asset: manager.getAssetSubscriber(),
198
- vault: pot.getSubscriber(),
199
- },
200
- invitationMakers: Far('invitation makers', {
201
- AdjustBalances: () =>
202
- zcf.makeInvitation(
203
- seatx => helper.adjustBalancesHook(seatx),
204
- 'AdjustBalances',
205
- ),
206
- CloseVault: () =>
207
- zcf.makeInvitation(seatx => helper.closeHook(seatx), 'CloseVault'),
208
- }),
209
- vault: pot,
210
- });
211
- };
212
-
213
- const publicFacet = augmentPublicFacet(
214
- harden({
215
- makeLoanInvitation: () =>
216
- zcf.makeInvitation(offerHandler, 'make stakeFactory'),
217
- makeReturnAttInvitation: att.publicFacet.makeReturnAttInvitation,
218
- }),
219
- );
220
-
221
- /** @type {ERef<StakeFactoryCreator>} */
222
- const creatorFacet = Far('stakeFactory creator', {
223
- provideAttestationMaker: att.creatorFacet.provideAttestationTool,
224
- makeCollectFeesInvitation: () => {
225
- return makeMakeCollectFeesInvitation(
226
- zcf,
227
- rewardPoolSeat,
228
- debtBrand,
229
- 'Minted',
230
- ).makeCollectFeesInvitation();
231
- },
232
- });
233
-
234
- return { publicFacet, creatorFacet: makeGovernorFacet(creatorFacet) };
235
- };
236
- harden(start);
@@ -1,455 +0,0 @@
1
- // @ts-check
2
- // @jessie-check
3
- import { AmountMath, AssetKind } from '@agoric/ertp';
4
- import { assertProposalShape } from '@agoric/zoe/src/contractSupport/index.js';
5
- import { ceilMultiplyBy } from '@agoric/zoe/src/contractSupport/ratio.js';
6
- import { makePublishKit } from '@agoric/notifier';
7
- import { bindAllMethods } from '@agoric/internal';
8
- import { M, matches } from '@agoric/store';
9
- import { defineKindMulti } from '@agoric/vat-data';
10
- import { makeTracer } from '../makeTracer.js';
11
- import { addSubtract, assertOnlyKeys, stageDelta } from '../contractSupport.js';
12
- import { calculateCurrentDebt, reverseInterest } from '../interest-math.js';
13
- import { ManagerKW as KW } from './constants.js';
14
-
15
- const { details: X, quote: q } = assert;
16
-
17
- const trace = makeTracer('R1');
18
-
19
- /**
20
- * Calculate the fee, the amount to mint and the resulting debt.
21
- *
22
- * @param {Ratio} feeCoeff fee coefficient
23
- * @param {Amount} currentDebt
24
- * @param {Amount} giveAmount
25
- * @param {Amount} wantAmount
26
- */
27
- const calculateFee = (feeCoeff, currentDebt, giveAmount, wantAmount) => {
28
- const fee = ceilMultiplyBy(wantAmount, feeCoeff);
29
- const toMint = AmountMath.add(wantAmount, fee);
30
- const newDebt = addSubtract(currentDebt, toMint, giveAmount);
31
- return { newDebt, toMint, fee };
32
- };
33
-
34
- /**
35
- * @typedef {Readonly<{
36
- * collateralBrand: Brand,
37
- * debtBrand: Brand,
38
- * manager: import('./stakeFactoryManager.js').StakeFactoryManager,
39
- * subscriber: Subscriber<unknown>
40
- * vaultSeat: ZCFSeat,
41
- * zcf: ZCF,
42
- * }>} ImmutableState
43
- * @typedef {{
44
- * open: boolean,
45
- * debtSnapshot: Amount<'nat'>,
46
- * interestSnapshot: Ratio,
47
- * publisher: Publisher<unknown> | null,
48
- * }} MutableState
49
- * @typedef {MutableState & ImmutableState} State
50
- * @typedef {{
51
- * state: State,
52
- * facets: {
53
- * helper: import('@agoric/vat-data/src/types').KindFacet<typeof helperBehavior>,
54
- * pot: import('@agoric/vat-data/src/types').KindFacet<typeof potBehavior>,
55
- * },
56
- * }} MethodContext
57
- */
58
-
59
- /**
60
- * Make stakeFactory kit state
61
- *
62
- * @param {ZCF} zcf
63
- * @param {ZCFSeat} startSeat
64
- * @param {import('./stakeFactoryManager.js').StakeFactoryManager} manager
65
- * @returns {State}
66
- */
67
- const initState = (zcf, startSeat, manager) => {
68
- const collateralBrand = manager.getCollateralBrand();
69
- const debtBrand = manager.getDebtBrand();
70
-
71
- const { zcfSeat: vaultSeat } = zcf.makeEmptySeatKit();
72
-
73
- const emptyDebt = AmountMath.makeEmpty(debtBrand);
74
-
75
- const initialDebt = (() => {
76
- assertProposalShape(startSeat, {
77
- give: { [KW.Attestation]: null },
78
- want: { [KW.Debt]: null },
79
- });
80
- const {
81
- give: { [KW.Attestation]: attestationGiven },
82
- want: { [KW.Debt]: runWanted },
83
- } = startSeat.getProposal();
84
-
85
- const { maxDebt } = manager.maxDebtForLien(attestationGiven);
86
- AmountMath.isGTE(maxDebt, runWanted) ||
87
- assert.fail(
88
- X`wanted ${runWanted}, more than max debt (${maxDebt}) for ${attestationGiven}`,
89
- );
90
-
91
- const { newDebt, fee, toMint } = calculateFee(
92
- manager.getLoanFee(),
93
- emptyDebt,
94
- emptyDebt,
95
- runWanted,
96
- );
97
- !AmountMath.isEmpty(fee) ||
98
- assert.fail(
99
- X`loan requested (${runWanted}) is too small; cannot accrue interest`,
100
- );
101
- assert(AmountMath.isEqual(newDebt, toMint), X`loan fee mismatch`);
102
- trace('init', { runWanted, fee, attestationGiven });
103
-
104
- vaultSeat.incrementBy(
105
- startSeat.decrementBy(harden({ [KW.Attestation]: attestationGiven })),
106
- );
107
-
108
- manager.mintAndReallocate(toMint, fee, startSeat, vaultSeat);
109
-
110
- startSeat.exit();
111
- return newDebt;
112
- })();
113
- manager.applyDebtDelta(emptyDebt, initialDebt);
114
-
115
- const { publisher, subscriber } = makePublishKit();
116
-
117
- /** @type {ImmutableState} */
118
- const immutable = {
119
- collateralBrand,
120
- debtBrand,
121
- manager,
122
- subscriber,
123
- vaultSeat,
124
- zcf,
125
- };
126
- return {
127
- ...immutable,
128
- open: true,
129
- // Two values from the same moment
130
- interestSnapshot: manager.getCompoundedInterest(),
131
- debtSnapshot: initialDebt,
132
- publisher,
133
- };
134
- };
135
- const helperBehavior = {
136
- /**
137
- * @param {MethodContext} context
138
- * @param {ZCFSeat} seat
139
- */
140
- getCollateralAllocated: ({ state }, seat) =>
141
- seat.getAmountAllocated(KW.Attestation, state.collateralBrand),
142
- /**
143
- * @param {MethodContext} context
144
- * @param {ZCFSeat} seat
145
- */
146
- getMintedAllocated: ({ state }, seat) =>
147
- seat.getAmountAllocated(KW.Debt, state.debtBrand),
148
- /**
149
- * @param {MethodContext} context
150
- */
151
- getCollateralAmount: ({ state, facets }) => {
152
- const { collateralBrand, vaultSeat } = state;
153
- const { helper } = facets;
154
- const emptyCollateral = AmountMath.makeEmpty(
155
- collateralBrand,
156
- AssetKind.COPY_BAG,
157
- );
158
- // getCollateralAllocated would return final allocations
159
- return vaultSeat.hasExited()
160
- ? emptyCollateral
161
- : helper.getCollateralAllocated(vaultSeat);
162
- },
163
-
164
- /**
165
- * @param {MethodContext} context
166
- * @param {boolean} newActive */
167
- snapshotState: ({ state, facets }, newActive) => {
168
- const { debtSnapshot: debt, interestSnapshot: interest } = state;
169
- const { helper } = facets;
170
- /** @type {VaultNotification} */
171
- const result = harden({
172
- debtSnapshot: { debt, interest },
173
- locked: helper.getCollateralAmount(),
174
- // newPhase param is so that makeTransferInvitation can finish without setting the vault's phase
175
- // TODO refactor https://github.com/Agoric/agoric-sdk/issues/4415
176
- vaultState: newActive ? 'active' : 'closed',
177
- });
178
- return result;
179
- },
180
-
181
- /**
182
- * call this whenever anything changes!
183
- *
184
- * @param {MethodContext} context
185
- */
186
- updateUiState: async ({ state, facets }) => {
187
- const { open: active, publisher } = state;
188
- if (!publisher) {
189
- console.warn('updateUiState called after ui.publisher removed');
190
- return;
191
- }
192
- const uiState = facets.helper.snapshotState(active);
193
- trace('updateUiState', uiState);
194
-
195
- if (active) {
196
- publisher.publish(uiState);
197
- } else {
198
- publisher.finish(uiState);
199
- state.publisher = null;
200
- }
201
- },
202
-
203
- /**
204
- * Called whenever the debt is paid or created through a transaction,
205
- * but not for interest accrual.
206
- *
207
- * @param {MethodContext} context
208
- * @param {Amount} newDebt - principal and all accrued interest
209
- */
210
- updateDebtSnapshot: ({ state }, newDebt) => {
211
- const { manager } = state;
212
- // update local state
213
- state.debtSnapshot = newDebt;
214
- state.interestSnapshot = manager.getCompoundedInterest();
215
- },
216
-
217
- /**
218
- * Update the debt balance and propagate upwards to
219
- * maintain aggregate debt and liquidation order.
220
- *
221
- * @param {MethodContext} context
222
- * @param {Amount} oldDebt - prior principal and all accrued interest
223
- * @param {Amount} newDebt - actual principal and all accrued interest
224
- */
225
- updateDebtAccounting: ({ state, facets }, oldDebt, newDebt) => {
226
- const { manager } = state;
227
- const { helper } = facets;
228
- helper.updateDebtSnapshot(newDebt);
229
- // update vault manager which tracks total debt
230
- manager.applyDebtDelta(oldDebt, newDebt);
231
- },
232
-
233
- /**
234
- * @param {MethodContext} context
235
- */
236
- assertVaultHoldsNoMinted: ({ state, facets }) => {
237
- const { vaultSeat } = state;
238
- const { helper } = facets;
239
- AmountMath.isEmpty(helper.getMintedAllocated(vaultSeat)) ||
240
- assert.fail(X`Vault should be empty of debt`);
241
- },
242
-
243
- /**
244
- * Adjust principal and collateral (atomically for offer safety)
245
- *
246
- * @param {MethodContext} context
247
- * @param {ZCFSeat} clientSeat
248
- */
249
- adjustBalancesHook: ({ state, facets }, clientSeat) => {
250
- const { collateralBrand, debtBrand, manager, vaultSeat } = state;
251
- const { helper, pot } = facets;
252
- assert(state.open);
253
-
254
- const proposal = clientSeat.getProposal();
255
- assertOnlyKeys(proposal, [KW.Attestation, KW.Debt]);
256
-
257
- const debt = pot.getCurrentDebt();
258
- const collateral = helper.getCollateralAllocated(vaultSeat);
259
-
260
- const emptyCollateral = AmountMath.makeEmpty(
261
- collateralBrand,
262
- AssetKind.COPY_BAG,
263
- );
264
- const giveColl = proposal.give.Attestation || emptyCollateral;
265
- const wantColl = proposal.want.Attestation || emptyCollateral;
266
-
267
- // new = after the transaction gets applied
268
- const newCollateral = addSubtract(collateral, giveColl, wantColl);
269
- // max debt supported by current Collateral as modified by proposal
270
- const { amountLiened, maxDebt: newMaxDebt } =
271
- manager.maxDebtForLien(newCollateral);
272
-
273
- const emptyDebt = AmountMath.makeEmpty(debtBrand);
274
- const give = AmountMath.min(proposal.give.Debt || emptyDebt, debt);
275
- const want = proposal.want.Debt || emptyDebt;
276
- const giveDebtOnly = matches(
277
- proposal,
278
- harden({ give: { [KW.Debt]: M.record() }, want: {}, exit: M.any() }),
279
- );
280
-
281
- // Calculate the fee, the amount to mint and the resulting debt. We'll
282
- // verify that the target debt doesn't violate the collateralization ratio,
283
- // then mint, reallocate, and burn.
284
- const { newDebt, fee, toMint } = calculateFee(
285
- manager.getLoanFee(),
286
- debt,
287
- give,
288
- want,
289
- );
290
- assert(
291
- giveDebtOnly || AmountMath.isGTE(newMaxDebt, newDebt),
292
- `cannot borrow ${q(newDebt)} against ${q(amountLiened)}; max is ${q(
293
- newMaxDebt,
294
- )}`,
295
- );
296
-
297
- trace('adjustBalancesHook', {
298
- targetCollateralAmount: newCollateral,
299
- vaultCollateral: newCollateral,
300
- fee,
301
- toMint,
302
- newDebt,
303
- });
304
-
305
- stageDelta(clientSeat, vaultSeat, giveColl, wantColl, KW.Attestation);
306
- stageDelta(clientSeat, vaultSeat, give, emptyDebt, KW.Debt);
307
- manager.mintAndReallocate(toMint, fee, clientSeat, vaultSeat);
308
-
309
- // parent needs to know about the change in debt
310
- helper.updateDebtAccounting(debt, newDebt);
311
-
312
- manager.burnDebt(give, vaultSeat);
313
-
314
- helper.assertVaultHoldsNoMinted();
315
-
316
- void helper.updateUiState();
317
- clientSeat.exit();
318
-
319
- return 'We have adjusted your balances; thank you for your business.';
320
- },
321
-
322
- /**
323
- * Given sufficient Minted payoff, refund the attestation.
324
- *
325
- * @type {import('@agoric/vat-data/src/types').PlusContext<MethodContext, OfferHandler>}
326
- */
327
- closeHook: ({ state, facets }, seat) => {
328
- const { debtBrand, manager, vaultSeat, zcf } = state;
329
- const { helper, pot } = facets;
330
- assert(state.open);
331
- assertProposalShape(seat, {
332
- give: { [KW.Debt]: null },
333
- want: { [KW.Attestation]: null },
334
- });
335
-
336
- const currentDebt = pot.getCurrentDebt();
337
- const {
338
- give: { [KW.Debt]: runOffered },
339
- } = seat.getProposal();
340
- AmountMath.isGTE(runOffered, currentDebt) ||
341
- assert.fail(
342
- X`Offer ${runOffered} is not sufficient to pay off debt ${currentDebt}`,
343
- );
344
- vaultSeat.incrementBy(seat.decrementBy(harden({ [KW.Debt]: currentDebt })));
345
- seat.incrementBy(
346
- vaultSeat.decrementBy(
347
- harden({ Attestation: vaultSeat.getAmountAllocated('Attestation') }),
348
- ),
349
- );
350
-
351
- zcf.reallocate(seat, vaultSeat);
352
-
353
- manager.burnDebt(currentDebt, vaultSeat);
354
- state.open = false;
355
- helper.updateDebtSnapshot(AmountMath.makeEmpty(debtBrand));
356
- void helper.updateUiState();
357
- helper.assertVaultHoldsNoMinted();
358
- seat.exit();
359
-
360
- return 'Your stakeFactory is closed; thank you for your business.';
361
- },
362
- };
363
-
364
- const potBehavior = {
365
- /** @param {MethodContext} context */
366
- getSubscriber: ({ state }) => state.subscriber,
367
- /** @param {MethodContext} context */
368
- makeAdjustBalancesInvitation: ({ state, facets }) => {
369
- const { zcf } = state;
370
- const { helper } = facets;
371
- assert(state.open);
372
- return zcf.makeInvitation(
373
- seat => helper.adjustBalancesHook(seat),
374
- 'AdjustBalances',
375
- );
376
- },
377
- /** @param {MethodContext} context */
378
- makeCloseInvitation: ({ state, facets }) => {
379
- const { zcf } = state;
380
- const { helper } = facets;
381
- assert(state.open);
382
- return zcf.makeInvitation(seat => helper.closeHook(seat), 'CloseVault');
383
- },
384
- /**
385
- * The actual current debt, including accrued interest.
386
- *
387
- * This looks like a simple getter but it does a lot of the heavy lifting for
388
- * interest accrual. Rather than updating all records when interest accrues,
389
- * the vault manager updates just its rolling compounded interest. Here we
390
- * calculate what the current debt is given what's recorded in this vault and
391
- * what interest has compounded since this vault record was written.
392
- *
393
- * @see getNormalizedDebt
394
- * @param {MethodContext} context
395
- * @returns {Amount<'nat'>}
396
- */
397
- getCurrentDebt: ({ state }) => {
398
- return calculateCurrentDebt(
399
- state.debtSnapshot,
400
- state.interestSnapshot,
401
- state.manager.getCompoundedInterest(),
402
- );
403
- },
404
- /** @param {MethodContext} context */
405
- getNormalizedDebt: ({ state }) =>
406
- reverseInterest(state.debtSnapshot, state.interestSnapshot),
407
- };
408
-
409
- const behavior = {
410
- helper: helperBehavior,
411
- pot: potBehavior,
412
- };
413
-
414
- /**
415
- * @param {MethodContext} context
416
- */
417
- const finish = ({ facets }) => {
418
- const { helper } = facets;
419
- void helper.updateUiState();
420
- };
421
-
422
- /**
423
- * Make stakeFactory kit, subject to stakeFactory terms.
424
- *
425
- * @param {ZCF} zcf
426
- * @param {ZCFSeat} startSeat
427
- * @param {import('./stakeFactoryManager.js').StakeFactoryManager} manager
428
- * @throws {Error} if startSeat proposal is not consistent with governance parameters in manager
429
- */
430
- const makeStakeFactoryKitInternal = defineKindMulti(
431
- 'stakeFactoryKit',
432
- initState,
433
- behavior,
434
- { finish },
435
- );
436
-
437
- /**
438
- * Make stakeFactory kit, subject to stakeFactory terms.
439
- *
440
- * TODO refactor to remove this wrapper around the kind and to stop using
441
- * `bindAllMethods`.
442
- *
443
- * @param {ZCF} zcf
444
- * @param {ZCFSeat} startSeat
445
- * @param {import('./stakeFactoryManager.js').StakeFactoryManager} manager
446
- * @throws {Error} if startSeat proposal is not consistent with governance parameters in manager
447
- */
448
- export const makeStakeFactoryKit = (zcf, startSeat, manager) => {
449
- const { helper, pot } = makeStakeFactoryKitInternal(zcf, startSeat, manager);
450
- return harden({
451
- // XXX work- around for change from auto - binding
452
- helper: bindAllMethods(helper),
453
- pot,
454
- });
455
- };