@agoric/inter-protocol 0.13.4-pismo-dev-0d5327f.0 → 0.14.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 (141) hide show
  1. package/CHANGELOG.md +287 -0
  2. package/README.md +26 -20
  3. package/bundles/bundle-auctioneer-js-meta.json +722 -0
  4. package/bundles/bundle-auctioneer.js +1 -0
  5. package/bundles/bundle-econCommitteeCharter-js-meta.json +514 -0
  6. package/bundles/bundle-econCommitteeCharter.js +1 -0
  7. package/bundles/bundle-feeDistributor-js-meta.json +458 -0
  8. package/bundles/bundle-feeDistributor.js +1 -1
  9. package/bundles/bundle-fluxAggregatorKit-js-meta.json +674 -0
  10. package/bundles/bundle-fluxAggregatorKit.js +1 -0
  11. package/bundles/bundle-psm-js-meta.json +666 -0
  12. package/bundles/bundle-psm.js +1 -1
  13. package/bundles/bundle-reserve-js-meta.json +662 -0
  14. package/bundles/bundle-reserve.js +1 -1
  15. package/bundles/bundle-scaledPriceAuthority-js-meta.json +542 -0
  16. package/bundles/bundle-scaledPriceAuthority.js +1 -1
  17. package/bundles/bundle-vaultFactory-js-meta.json +786 -0
  18. package/bundles/bundle-vaultFactory.js +1 -1
  19. package/exported.js +0 -2
  20. package/package.json +34 -31
  21. package/scripts/add-collateral-core.js +14 -4
  22. package/scripts/build-bundles.js +9 -2
  23. package/scripts/deploy-contracts.js +1 -4
  24. package/scripts/init-core.js +20 -38
  25. package/scripts/invite-committee-core.js +1 -1
  26. package/scripts/manual-price-feed.js +2 -2
  27. package/scripts/price-feed-core.js +7 -6
  28. package/scripts/start-local-chain.sh +84 -0
  29. package/src/auction/auctionBook.js +755 -0
  30. package/src/auction/auctioneer.js +720 -0
  31. package/src/auction/offerBook.js +221 -0
  32. package/src/auction/params.js +174 -0
  33. package/src/auction/scheduleMath.js +167 -0
  34. package/src/auction/scheduler.js +370 -0
  35. package/src/auction/sortedOffers.js +136 -0
  36. package/src/auction/util.js +55 -0
  37. package/src/clientSupport.js +324 -0
  38. package/src/collectFees.js +8 -14
  39. package/src/contractSupport.js +24 -68
  40. package/src/econCommitteeCharter.js +161 -77
  41. package/src/feeDistributor.js +60 -20
  42. package/src/index.js +2 -0
  43. package/src/interest-math.js +1 -4
  44. package/src/interest.js +20 -13
  45. package/src/price/README.md +57 -0
  46. package/src/price/fluxAggregatorContract.js +190 -0
  47. package/src/price/fluxAggregatorKit.js +375 -0
  48. package/src/price/priceOracleKit.js +127 -0
  49. package/src/price/roundsManager.js +726 -0
  50. package/src/proposals/addAssetToVault.js +89 -94
  51. package/src/proposals/committee-proposal.js +141 -40
  52. package/src/proposals/core-proposal.js +100 -167
  53. package/src/proposals/econ-behaviors.js +320 -564
  54. package/src/proposals/price-feed-proposal.js +175 -78
  55. package/src/proposals/startEconCommittee.js +25 -12
  56. package/src/proposals/startPSM.js +231 -211
  57. package/src/proposals/utils.js +31 -17
  58. package/src/psm/README.md +71 -0
  59. package/src/psm/psm.js +272 -160
  60. package/src/psm/types.js +2 -0
  61. package/src/reserve/assetReserve.js +56 -413
  62. package/src/reserve/assetReserveKit.js +303 -0
  63. package/src/reserve/doc.md +1 -3
  64. package/src/reserve/params.js +2 -5
  65. package/src/typeGuards.js +13 -0
  66. package/src/vaultFactory/Liquidation.md +100 -0
  67. package/src/vaultFactory/burn.js +2 -1
  68. package/src/vaultFactory/liquidation.js +270 -108
  69. package/src/vaultFactory/math.js +95 -0
  70. package/src/vaultFactory/orderedVaultStore.js +0 -1
  71. package/src/vaultFactory/params.js +133 -112
  72. package/src/vaultFactory/prioritizedVaults.js +36 -79
  73. package/src/vaultFactory/storeUtils.js +67 -9
  74. package/src/vaultFactory/type-imports.js +2 -0
  75. package/src/vaultFactory/types.js +22 -26
  76. package/src/vaultFactory/vault.js +772 -709
  77. package/src/vaultFactory/vaultDirector.js +480 -483
  78. package/src/vaultFactory/vaultFactory.js +99 -60
  79. package/src/vaultFactory/vaultHolder.js +121 -95
  80. package/src/vaultFactory/vaultKit.js +39 -31
  81. package/src/vaultFactory/vaultManager.js +1249 -868
  82. package/bundles/bundle-amm-meta.js +0 -618
  83. package/bundles/bundle-amm.js +0 -1
  84. package/bundles/bundle-feeDistributor-meta.js +0 -346
  85. package/bundles/bundle-interchainPool-meta.js +0 -534
  86. package/bundles/bundle-interchainPool.js +0 -1
  87. package/bundles/bundle-liquidateIncrementally-meta.js +0 -442
  88. package/bundles/bundle-liquidateIncrementally.js +0 -1
  89. package/bundles/bundle-liquidateMinimum-meta.js +0 -442
  90. package/bundles/bundle-liquidateMinimum.js +0 -1
  91. package/bundles/bundle-psm-meta.js +0 -538
  92. package/bundles/bundle-psmCharter-meta.js +0 -418
  93. package/bundles/bundle-psmCharter.js +0 -1
  94. package/bundles/bundle-reserve-meta.js +0 -542
  95. package/bundles/bundle-scaledPriceAuthority-meta.js +0 -442
  96. package/bundles/bundle-stakeFactory-meta.js +0 -574
  97. package/bundles/bundle-stakeFactory.js +0 -1
  98. package/bundles/bundle-vaultFactory-meta.js +0 -598
  99. package/scripts/add-initial-liquidity.js +0 -180
  100. package/src/collect.js +0 -13
  101. package/src/interchainPool.js +0 -135
  102. package/src/makeTracer.js +0 -36
  103. package/src/my-lien.js +0 -85
  104. package/src/proposals/demoIssuers.js +0 -685
  105. package/src/proposals/sim-behaviors.js +0 -40
  106. package/src/psm/psmCharter.js +0 -139
  107. package/src/stakeFactory/README.md +0 -62
  108. package/src/stakeFactory/attestation.js +0 -267
  109. package/src/stakeFactory/attestationTool.js +0 -66
  110. package/src/stakeFactory/constants.js +0 -16
  111. package/src/stakeFactory/params.js +0 -31
  112. package/src/stakeFactory/stakeFactory.js +0 -236
  113. package/src/stakeFactory/stakeFactoryKit.js +0 -455
  114. package/src/stakeFactory/stakeFactoryManager.js +0 -296
  115. package/src/stakeFactory/types.js +0 -42
  116. package/src/vaultFactory/liquidateIncrementally.js +0 -350
  117. package/src/vaultFactory/liquidateMinimum.js +0 -100
  118. package/src/vpool-xyk-amm/AttackersGuide.md +0 -89
  119. package/src/vpool-xyk-amm/addLiquidity.js +0 -222
  120. package/src/vpool-xyk-amm/addPool.js +0 -197
  121. package/src/vpool-xyk-amm/constantProduct/AMM-Trade.jpeg +0 -0
  122. package/src/vpool-xyk-amm/constantProduct/README.md +0 -204
  123. package/src/vpool-xyk-amm/constantProduct/calcFees.js +0 -99
  124. package/src/vpool-xyk-amm/constantProduct/calcSwapPrices.js +0 -85
  125. package/src/vpool-xyk-amm/constantProduct/core.js +0 -153
  126. package/src/vpool-xyk-amm/constantProduct/defaults.js +0 -5
  127. package/src/vpool-xyk-amm/constantProduct/getXY.js +0 -52
  128. package/src/vpool-xyk-amm/constantProduct/internal-types.js +0 -116
  129. package/src/vpool-xyk-amm/constantProduct/invariants.js +0 -43
  130. package/src/vpool-xyk-amm/constantProduct/swap.js +0 -272
  131. package/src/vpool-xyk-amm/constantProduct/types.js +0 -32
  132. package/src/vpool-xyk-amm/doublePool.js +0 -194
  133. package/src/vpool-xyk-amm/estimate.js +0 -155
  134. package/src/vpool-xyk-amm/multipoolMarketMaker.js +0 -520
  135. package/src/vpool-xyk-amm/params.js +0 -61
  136. package/src/vpool-xyk-amm/pool.js +0 -396
  137. package/src/vpool-xyk-amm/priceAuthority.js +0 -94
  138. package/src/vpool-xyk-amm/removeLiquidity.js +0 -31
  139. package/src/vpool-xyk-amm/singlePool.js +0 -73
  140. package/src/vpool-xyk-amm/swap.js +0 -69
  141. package/src/vpool-xyk-amm/types.js +0 -154
@@ -1,16 +1,17 @@
1
- // @ts-check
1
+ // @jessie-check
2
2
 
3
3
  import './types.js';
4
4
 
5
5
  import {
6
6
  CONTRACT_ELECTORATE,
7
7
  makeParamManagerSync,
8
- makeParamManager,
9
8
  ParamTypes,
10
9
  } from '@agoric/governance';
11
10
  import { makeStoredPublisherKit } from '@agoric/notifier';
12
- import { M } from '@agoric/store';
13
- import { TimeMath } from '@agoric/swingset-vat/src/vats/timer/timeMath.js';
11
+ import { M, makeScalarMapStore } from '@agoric/store';
12
+ import { TimeMath } from '@agoric/time';
13
+ import { provideDurableMapStore } from '@agoric/vat-data';
14
+ import { subtractRatios } from '@agoric/zoe/src/contractSupport/ratio.js';
14
15
  import { amountPattern, ratioPattern } from '../contractSupport.js';
15
16
 
16
17
  export const CHARGING_PERIOD_KEY = 'ChargingPeriod';
@@ -18,41 +19,41 @@ export const RECORDING_PERIOD_KEY = 'RecordingPeriod';
18
19
 
19
20
  export const DEBT_LIMIT_KEY = 'DebtLimit';
20
21
  export const LIQUIDATION_MARGIN_KEY = 'LiquidationMargin';
22
+ export const LIQUIDATION_PADDING_KEY = 'LiquidationPadding';
21
23
  export const LIQUIDATION_PENALTY_KEY = 'LiquidationPenalty';
22
24
  export const INTEREST_RATE_KEY = 'InterestRate';
23
- export const LOAN_FEE_KEY = 'LoanFee';
24
- export const LIQUIDATION_INSTALL_KEY = 'LiquidationInstall';
25
- export const LIQUIDATION_TERMS_KEY = 'LiquidationTerms';
25
+ export const MINT_FEE_KEY = 'MintFee';
26
26
  export const MIN_INITIAL_DEBT_KEY = 'MinInitialDebt';
27
27
  export const SHORTFALL_INVITATION_KEY = 'ShortfallInvitation';
28
+ export const ENDORSED_UI_KEY = 'EndorsedUI';
29
+
30
+ export const vaultDirectorParamTypes = {
31
+ [MIN_INITIAL_DEBT_KEY]: ParamTypes.AMOUNT,
32
+ [CHARGING_PERIOD_KEY]: ParamTypes.NAT,
33
+ [RECORDING_PERIOD_KEY]: ParamTypes.NAT,
34
+ [ENDORSED_UI_KEY]: ParamTypes.STRING,
35
+ };
36
+ harden(vaultDirectorParamTypes);
28
37
 
29
38
  /**
30
- * @param {Amount} electorateInvitationAmount
31
- * @param {Installation} liquidationInstall
32
- * @param {import('./liquidation.js').LiquidationTerms} liquidationTerms
33
- * @param {Amount} minInitialDebt
34
- * @param {Amount} shortfallInvitationAmount
39
+ * @param {Amount<'set'>} electorateInvitationAmount
40
+ * @param {Amount<'nat'>} minInitialDebt
41
+ * @param {Amount<'set'>} shortfallInvitationAmount
42
+ * @param {string} endorsedUi
43
+ * @param {InterestTiming} interestTiming
35
44
  */
36
45
  const makeVaultDirectorParams = (
37
46
  electorateInvitationAmount,
38
- liquidationInstall,
39
- liquidationTerms,
40
47
  minInitialDebt,
41
48
  shortfallInvitationAmount,
49
+ endorsedUi,
50
+ interestTiming,
42
51
  ) => {
43
52
  return harden({
44
53
  [CONTRACT_ELECTORATE]: {
45
54
  type: ParamTypes.INVITATION,
46
55
  value: electorateInvitationAmount,
47
56
  },
48
- [LIQUIDATION_INSTALL_KEY]: {
49
- type: ParamTypes.INSTALLATION,
50
- value: liquidationInstall,
51
- },
52
- [LIQUIDATION_TERMS_KEY]: {
53
- type: ParamTypes.UNKNOWN,
54
- value: liquidationTerms,
55
- },
56
57
  [MIN_INITIAL_DEBT_KEY]: {
57
58
  type: ParamTypes.AMOUNT,
58
59
  value: minInitialDebt,
@@ -61,136 +62,156 @@ const makeVaultDirectorParams = (
61
62
  type: ParamTypes.INVITATION,
62
63
  value: shortfallInvitationAmount,
63
64
  },
65
+ [ENDORSED_UI_KEY]: { type: ParamTypes.STRING, value: endorsedUi },
66
+ [CHARGING_PERIOD_KEY]: {
67
+ type: ParamTypes.NAT,
68
+ value: TimeMath.relValue(interestTiming.chargingPeriod),
69
+ },
70
+ [RECORDING_PERIOD_KEY]: {
71
+ type: ParamTypes.NAT,
72
+ value: TimeMath.relValue(interestTiming.recordingPeriod),
73
+ },
64
74
  });
65
75
  };
76
+ harden(makeVaultDirectorParams);
66
77
 
67
78
  /** @typedef {import('@agoric/governance/src/contractGovernance/typedParamManager').ParamTypesMapFromRecord<ReturnType<typeof makeVaultDirectorParams>>} VaultDirectorParams */
68
79
 
80
+ /** @type {(liquidationMargin: Ratio) => Ratio} */
81
+ const zeroRatio = liquidationMargin =>
82
+ subtractRatios(liquidationMargin, liquidationMargin);
83
+
69
84
  /**
70
85
  * @param {import('@agoric/notifier').StoredPublisherKit<GovernanceSubscriptionState>} publisherKit
71
86
  * @param {VaultManagerParamValues} initial
72
87
  */
73
- const makeVaultParamManager = (publisherKit, initial) =>
88
+ export const makeVaultParamManager = (
89
+ publisherKit,
90
+ {
91
+ debtLimit,
92
+ interestRate,
93
+ liquidationMargin,
94
+ liquidationPadding = zeroRatio(liquidationMargin),
95
+ liquidationPenalty,
96
+ mintFee,
97
+ },
98
+ ) =>
74
99
  makeParamManagerSync(publisherKit, {
75
- [DEBT_LIMIT_KEY]: [ParamTypes.AMOUNT, initial.debtLimit],
76
- [LIQUIDATION_MARGIN_KEY]: [ParamTypes.RATIO, initial.liquidationMargin],
77
- [LIQUIDATION_PENALTY_KEY]: [ParamTypes.RATIO, initial.liquidationPenalty],
78
- [INTEREST_RATE_KEY]: [ParamTypes.RATIO, initial.interestRate],
79
- [LOAN_FEE_KEY]: [ParamTypes.RATIO, initial.loanFee],
100
+ [DEBT_LIMIT_KEY]: [ParamTypes.AMOUNT, debtLimit],
101
+ [INTEREST_RATE_KEY]: [ParamTypes.RATIO, interestRate],
102
+ [LIQUIDATION_PADDING_KEY]: [ParamTypes.RATIO, liquidationPadding],
103
+ [LIQUIDATION_MARGIN_KEY]: [ParamTypes.RATIO, liquidationMargin],
104
+ [LIQUIDATION_PENALTY_KEY]: [ParamTypes.RATIO, liquidationPenalty],
105
+ [MINT_FEE_KEY]: [ParamTypes.RATIO, mintFee],
80
106
  });
81
107
  /** @typedef {ReturnType<typeof makeVaultParamManager>} VaultParamManager */
82
108
 
83
- export const vaultParamPattern = M.split(
109
+ export const vaultParamPattern = M.splitRecord(
84
110
  {
85
111
  liquidationMargin: ratioPattern,
86
112
  liquidationPenalty: ratioPattern,
87
113
  interestRate: ratioPattern,
88
- loanFee: ratioPattern,
114
+ mintFee: ratioPattern,
89
115
  debtLimit: amountPattern,
90
116
  },
91
- M.any(),
117
+ {
118
+ // optional for backwards compatibility, e.g. with loadgen
119
+ liquidationPadding: ratioPattern,
120
+ },
92
121
  );
93
122
 
94
123
  /**
95
- * @param {import('@agoric/notifier').StoredPublisherKit<GovernanceSubscriptionState>} publisherKit
96
- * @param {ERef<ZoeService>} zoe
97
- * @param {Invitation} electorateInvitation
98
- * @param {Installation} liquidationInstall
99
- * @param {object} liquidationTerms
100
- * @param {Amount} minInitialDebt
101
- * @param {Invitation} shortfallInvitation
102
- */
103
- const makeVaultDirectorParamManager = async (
104
- publisherKit,
105
- zoe,
106
- electorateInvitation,
107
- liquidationInstall,
108
- liquidationTerms,
109
- minInitialDebt,
110
- shortfallInvitation,
111
- ) => {
112
- return makeParamManager(
113
- publisherKit,
114
- {
115
- [CONTRACT_ELECTORATE]: [ParamTypes.INVITATION, electorateInvitation],
116
- [LIQUIDATION_INSTALL_KEY]: [ParamTypes.INSTALLATION, liquidationInstall],
117
- [LIQUIDATION_TERMS_KEY]: [ParamTypes.UNKNOWN, liquidationTerms],
118
- [MIN_INITIAL_DEBT_KEY]: [ParamTypes.AMOUNT, minInitialDebt],
119
- [SHORTFALL_INVITATION_KEY]: [ParamTypes.INVITATION, shortfallInvitation],
120
- },
121
- zoe,
122
- );
123
- };
124
-
125
- /**
126
- * @param {{storageNode: ERef<StorageNode>, marshaller: ERef<Marshaller>}} caps
127
124
  * @param {{
128
- * electorateInvitationAmount: Amount,
129
- * minInitialDebt: Amount,
125
+ * auctioneerPublicFacet: ERef<AuctioneerPublicFacet>,
126
+ * electorateInvitationAmount: Amount<'set'>,
127
+ * minInitialDebt: Amount<'nat'>,
130
128
  * bootstrapPaymentValue: bigint,
131
129
  * priceAuthority: ERef<PriceAuthority>,
132
- * timer: ERef<TimerService>,
130
+ * timer: ERef<import('@agoric/time/src/types').TimerService>,
133
131
  * reservePublicFacet: AssetReservePublicFacet,
134
- * liquidationInstall: Installation,
135
- * loanTiming: LoanTiming,
136
- * liquidationTerms: import('./liquidation.js').LiquidationTerms,
137
- * ammPublicFacet: XYKAMMPublicFacet,
138
- * shortfallInvitationAmount: Amount,
132
+ * interestTiming: InterestTiming,
133
+ * shortfallInvitationAmount: Amount<'set'>,
134
+ * endorsedUi?: string,
139
135
  * }} opts
140
136
  */
141
- const makeGovernedTerms = (
142
- { storageNode, marshaller },
143
- {
144
- ammPublicFacet,
145
- bootstrapPaymentValue,
146
- electorateInvitationAmount,
147
- liquidationInstall,
148
- liquidationTerms,
149
- loanTiming,
150
- minInitialDebt,
151
- priceAuthority,
152
- reservePublicFacet,
153
- timer,
154
- shortfallInvitationAmount,
155
- },
156
- ) => {
157
- const loanTimingParams = makeParamManagerSync(
158
- makeStoredPublisherKit(storageNode, marshaller, 'timingParams'),
159
- {
160
- [CHARGING_PERIOD_KEY]: [
161
- 'nat',
162
- TimeMath.relValue(loanTiming.chargingPeriod),
163
- ],
164
- [RECORDING_PERIOD_KEY]: [
165
- 'nat',
166
- TimeMath.relValue(loanTiming.recordingPeriod),
167
- ],
168
- },
169
- ).getParams();
170
-
137
+ export const makeGovernedTerms = ({
138
+ auctioneerPublicFacet,
139
+ bootstrapPaymentValue,
140
+ electorateInvitationAmount,
141
+ interestTiming,
142
+ minInitialDebt,
143
+ priceAuthority,
144
+ reservePublicFacet,
145
+ timer,
146
+ shortfallInvitationAmount,
147
+ endorsedUi = 'NO ENDORSEMENT',
148
+ }) => {
171
149
  return harden({
172
- ammPublicFacet,
150
+ auctioneerPublicFacet,
173
151
  priceAuthority,
174
- loanTimingParams,
175
152
  reservePublicFacet,
176
153
  timerService: timer,
177
154
  governedParams: makeVaultDirectorParams(
178
155
  electorateInvitationAmount,
179
- liquidationInstall,
180
- liquidationTerms,
181
156
  minInitialDebt,
182
157
  shortfallInvitationAmount,
158
+ endorsedUi,
159
+ interestTiming,
183
160
  ),
184
161
  bootstrapPaymentValue,
185
162
  });
186
163
  };
187
-
188
- harden(makeVaultParamManager);
189
- harden(makeVaultDirectorParamManager);
190
164
  harden(makeGovernedTerms);
165
+ /**
166
+ * Stop-gap which restores initial param values
167
+ * UNTIL https://github.com/Agoric/agoric-sdk/issues/5200
168
+ *
169
+ * NB: changes from initial values will be lost upon restart
170
+ *
171
+ * @param {import('@agoric/vat-data').Baggage} baggage
172
+ * @param {ERef<Marshaller>} marshaller
173
+ */
174
+ export const provideVaultParamManagers = (baggage, marshaller) => {
175
+ /** @type {MapStore<Brand, VaultParamManager>} */
176
+ const managers = makeScalarMapStore();
177
+
178
+ // the managers aren't durable but their arguments are
179
+ /** @type {MapStore<Brand, {storageNode: StorageNode, initialParamValues: VaultManagerParamValues}>} */
180
+ const managerArgs = provideDurableMapStore(
181
+ baggage,
182
+ 'vault param manager parts',
183
+ );
184
+
185
+ const makeManager = (brand, { storageNode, initialParamValues }) => {
186
+ const manager = makeVaultParamManager(
187
+ makeStoredPublisherKit(storageNode, marshaller, 'governance'),
188
+ initialParamValues,
189
+ );
190
+ managers.init(brand, manager);
191
+ return manager;
192
+ };
193
+
194
+ // restore from baggage
195
+ [...managerArgs.entries()].map(([brand, args]) => makeManager(brand, args));
191
196
 
192
- export {
193
- makeVaultDirectorParamManager,
194
- makeVaultParamManager,
195
- makeGovernedTerms,
197
+ return {
198
+ /**
199
+ *
200
+ * @param {Brand} brand
201
+ * @param {StorageNode} storageNode
202
+ * @param {VaultManagerParamValues} initialParamValues
203
+ */
204
+ addParamManager(brand, storageNode, initialParamValues) {
205
+ const args = harden({ storageNode, initialParamValues });
206
+ managerArgs.init(brand, args);
207
+ return makeManager(brand, args);
208
+ },
209
+ /**
210
+ * @param {Brand} brand
211
+ */
212
+ get(brand) {
213
+ return managers.get(brand);
214
+ },
215
+ };
196
216
  };
217
+ harden(provideVaultParamManagers);
@@ -1,22 +1,24 @@
1
- // @ts-check
2
1
  // @jessie-check
3
2
 
3
+ import { makeTracer } from '@agoric/internal';
4
4
  import { makeRatioFromAmounts } from '@agoric/zoe/src/contractSupport/index.js';
5
5
  import { AmountMath } from '@agoric/ertp';
6
- import { ratioGTE } from '@agoric/zoe/src/contractSupport/ratio.js';
7
6
  import { Far } from '@endo/marshal';
8
- import { keyEQ, keyLT } from '@agoric/store';
7
+ import { M } from '@agoric/vat-data';
8
+ import { makeScalarMapStore } from '@agoric/store';
9
9
  import { makeOrderedVaultStore } from './orderedVaultStore.js';
10
- import { fromVaultKey, toVaultKey } from './storeUtils.js';
11
- import { makeTracer } from '../makeTracer.js';
12
-
13
- const trace = makeTracer('PV', false);
10
+ import {
11
+ toVaultKey,
12
+ normalizedCollRatioKey,
13
+ normalizedCollRatio,
14
+ } from './storeUtils.js';
14
15
 
15
16
  /** @typedef {import('./vault').Vault} Vault */
16
17
  /** @typedef {import('./storeUtils.js').NormalizedDebt} NormalizedDebt */
17
18
 
19
+ const trace = makeTracer('PVaults', true);
20
+
18
21
  /**
19
- *
20
22
  * @param {Amount<'nat'>} debtAmount
21
23
  * @param {Amount<'nat'>} collateralAmount
22
24
  * @returns {Ratio}
@@ -32,7 +34,6 @@ const calculateDebtToCollateral = (debtAmount, collateralAmount) => {
32
34
  };
33
35
 
34
36
  /**
35
- *
36
37
  * @param {Vault} vault
37
38
  * @returns {Ratio}
38
39
  */
@@ -47,43 +48,15 @@ export const currentDebtToCollateral = vault =>
47
48
  * can be quickly found and liquidated.
48
49
  *
49
50
  * @param {MapStore<string, Vault>} store
50
- * @param {(highestRatio: Ratio) => void} [higherHighestCb] called when a new
51
51
  * vault has a higher debt ratio than the previous highest
52
52
  */
53
- export const makePrioritizedVaults = (store, higherHighestCb = () => {}) => {
53
+ export const makePrioritizedVaults = store => {
54
54
  const vaults = makeOrderedVaultStore(store);
55
55
 
56
- /**
57
- * Called back when there's a new highestRatio and it's higher than the previous.
58
- *
59
- * In other words, when a new highestRatio results from adding a vault. Removing the
60
- * first vault also changes the highest, but necessarily to a lower highest,
61
- * for which there are no use cases requiring notification.
62
- *
63
- * @param {(highestRatio: Ratio) => void} callback
64
- */
65
- const onHigherHighest = callback => {
66
- higherHighestCb = callback;
67
- };
68
-
69
- // To deal with fluctuating prices and varying collateralization, we schedule a
70
- // new request to the priceAuthority when some vault's debtToCollateral ratio
71
- // surpasses the current high-water mark. When the request that is at the
72
- // current high-water mark fires, we reschedule at the new (presumably
73
- // lower) rate.
74
- // Without this we'd be calling reschedulePriceCheck() unnecessarily
75
- /** @type {string=} */
76
- let firstKey;
77
-
78
- // Check if this ratio of debt to collateral would be the highest known. If
79
- // so, reset our highest and invoke the callback. This can be called on new
80
- // vaults and when we get a state update for a vault changing balances.
81
- /** @param {Ratio} collateralToDebt */
82
-
83
56
  /**
84
57
  * Ratio of the least-collateralized vault, if there is one.
85
58
  *
86
- * @returns {Ratio=} actual debt over collateral
59
+ * @returns {Ratio | undefined} actual debt over collateral
87
60
  */
88
61
  const highestRatio = () => {
89
62
  if (vaults.getSize() === 0) {
@@ -99,7 +72,6 @@ export const makePrioritizedVaults = (store, higherHighestCb = () => {}) => {
99
72
  };
100
73
 
101
74
  /**
102
- *
103
75
  * @param {NormalizedDebt} oldDebt
104
76
  * @param {Amount<'nat'>} oldCollateral
105
77
  * @param {string} vaultId
@@ -115,16 +87,10 @@ export const makePrioritizedVaults = (store, higherHighestCb = () => {}) => {
115
87
  */
116
88
  const removeVault = key => {
117
89
  const vault = vaults.removeByKey(key);
118
- trace('removeVault', key, fromVaultKey(key), 'when first:', firstKey);
119
- if (keyEQ(key, firstKey)) {
120
- const [secondKey] = vaults.keys();
121
- firstKey = secondKey;
122
- }
123
90
  return vault;
124
91
  };
125
92
 
126
93
  /**
127
- *
128
94
  * @param {NormalizedDebt} oldDebt
129
95
  * @param {Amount<'nat'>} oldCollateral
130
96
  * @param {string} vaultId
@@ -135,7 +101,6 @@ export const makePrioritizedVaults = (store, higherHighestCb = () => {}) => {
135
101
  };
136
102
 
137
103
  /**
138
- *
139
104
  * @param {VaultId} vaultId
140
105
  * @param {Vault} vault
141
106
  */
@@ -145,50 +110,42 @@ export const makePrioritizedVaults = (store, higherHighestCb = () => {}) => {
145
110
  !AmountMath.isEmpty(vault.getCollateralAmount()),
146
111
  'Tracked vaults must have collateral (be liquidatable)',
147
112
  );
148
- trace('addVault', key, 'when first:', firstKey);
149
- if (!firstKey || keyLT(key, firstKey)) {
150
- firstKey = key;
151
- higherHighestCb(currentDebtToCollateral(vault));
152
- }
153
113
  return key;
154
114
  };
155
115
 
156
- /**
157
- * Invoke a function for vaults with debt to collateral at or above the ratio.
158
- *
159
- * Results are returned in order of priority, with highest debt to collateral first.
160
- *
161
- * Redundant tags until https://github.com/Microsoft/TypeScript/issues/23857
162
- *
163
- * @param {Ratio} ratio
164
- * @yields {[string, Vault]>}
165
- * @returns {IterableIterator<[string, Vault]>}
166
- */
167
- // Allow generator function
168
- // eslint-disable-next-line func-names
169
- // eslint-disable-next-line no-restricted-syntax
170
- function* entriesPrioritizedGTE(ratio) {
171
- // TODO use a Pattern to limit the query https://github.com/Agoric/agoric-sdk/issues/4550
172
- for (const [key, vault] of vaults.entries()) {
173
- const debtToCollateral = currentDebtToCollateral(vault);
174
- if (ratioGTE(debtToCollateral, ratio)) {
175
- yield [key, vault];
176
- } else {
177
- // stop once we are below the target ratio
178
- break;
179
- }
116
+ const removeVaultsBelow = ({ margin, quote, interest }) => {
117
+ // crKey represents a collateralizationRatio based on the locked price, the
118
+ // interest charged so far, and the liquidation margin.
119
+ // We'll remove all vaults below that ratio, and return them.
120
+ const crKey = normalizedCollRatioKey(quote, interest, margin);
121
+
122
+ trace(
123
+ `Liquidating vaults worse than`,
124
+ normalizedCollRatio(quote, interest, margin),
125
+ );
126
+
127
+ /** @type {MapStore<string, Vault>} */
128
+ const vaultsRemoved = makeScalarMapStore();
129
+
130
+ for (const [key, vault] of vaults.entries(M.lte(crKey))) {
131
+ vaultsRemoved.init(key, vault);
132
+ vaults.removeByKey(key);
180
133
  }
181
- }
134
+
135
+ return vaultsRemoved;
136
+ };
182
137
 
183
138
  return Far('PrioritizedVaults', {
184
139
  addVault,
185
140
  entries: vaults.entries,
186
- entriesPrioritizedGTE,
187
141
  getCount: vaults.getSize,
188
142
  hasVaultByAttributes,
189
143
  highestRatio,
190
144
  removeVault,
191
145
  removeVaultByAttributes,
192
- onHigherHighest,
146
+ removeVaultsBelow,
147
+
148
+ // visible for testing
149
+ countVaultsBelow: crKey => vaults.getSize(M.lte(crKey)),
193
150
  });
194
151
  };
@@ -1,4 +1,5 @@
1
- // @ts-check
1
+ // @jessie-check
2
+
2
3
  /**
3
4
  * Module to improvise composite keys for orderedVaultStore until Collections
4
5
  * API supports them.
@@ -6,7 +7,17 @@
6
7
 
7
8
  // XXX importing these that are declared to be used only for testing
8
9
  // until @agoric/store supports composite keys
9
- import { makeDecodePassable, makeEncodePassable } from '@agoric/store';
10
+ import { makeDecodePassable, makeEncodePassable } from '@endo/marshal';
11
+ import {
12
+ getAmountIn,
13
+ getAmountOut,
14
+ natSafeMath,
15
+ } from '@agoric/zoe/src/contractSupport/index.js';
16
+ import { makeTracer } from '@agoric/internal';
17
+
18
+ const { multiply } = natSafeMath;
19
+
20
+ const trace = makeTracer('Store', true);
10
21
 
11
22
  /**
12
23
  * @typedef {import('@endo/marshal').PureData} PureData
@@ -25,7 +36,7 @@ import { makeDecodePassable, makeEncodePassable } from '@agoric/store';
25
36
  * @param {PureData} key
26
37
  * @returns {string}
27
38
  */
28
- const encodeData = makeEncodePassable();
39
+ export const encodeData = makeEncodePassable();
29
40
 
30
41
  // `makeDecodePassable` has three named options:
31
42
  // `decodeRemotable`, `decodeError`, and `decodePromise`.
@@ -36,7 +47,7 @@ const encodeData = makeEncodePassable();
36
47
  * @param {string} encoded
37
48
  * @returns {PureData}
38
49
  */
39
- const decodeData = makeDecodePassable();
50
+ export const decodeData = makeDecodePassable();
40
51
 
41
52
  /**
42
53
  * @param {number} n
@@ -86,7 +97,7 @@ const collateralizationRatio = (normalizedDebt, collateral) => {
86
97
  * @returns {string} lexically sortable string in which highest
87
98
  * debt-to-collateral is earliest
88
99
  */
89
- const toVaultKey = (normalizedDebt, collateral, vaultId) => {
100
+ export const toVaultKey = (normalizedDebt, collateral, vaultId) => {
90
101
  assert(normalizedDebt);
91
102
  assert(collateral);
92
103
  assert(vaultId);
@@ -95,19 +106,66 @@ const toVaultKey = (normalizedDebt, collateral, vaultId) => {
95
106
  const numberPart = encodeNumber(
96
107
  collateralizationRatio(normalizedDebt, collateral),
97
108
  );
109
+
110
+ trace(`To Vault Key `, collateralizationRatio(normalizedDebt, collateral));
98
111
  return `${numberPart}:${vaultId}`;
99
112
  };
113
+ harden(toVaultKey);
100
114
 
101
115
  /**
102
116
  * @param {string} key
103
117
  * @returns {[normalizedCollateralization: number, vaultId: VaultId]}
104
118
  */
105
- const fromVaultKey = key => {
119
+ export const fromVaultKey = key => {
106
120
  const [numberPart, vaultIdPart] = key.split(':');
107
121
  return [decodeNumber(numberPart), vaultIdPart];
108
122
  };
109
-
110
123
  harden(fromVaultKey);
111
- harden(toVaultKey);
112
124
 
113
- export { fromVaultKey, toVaultKey };
125
+ /**
126
+ * Create a float representing a Normalized Collateralization Ratio that can be
127
+ * compared to the NCRs of vaults. We want a float with as much resolution as we
128
+ * can get, so we multiply out the numerator and the denominator, and only
129
+ * divide the results once.
130
+ *
131
+ * For use by `normalizedCollRatioKey` and tests.
132
+ *
133
+ * @param {PriceQuote} quote
134
+ * @param {Ratio} compoundedInterest
135
+ * @param {Ratio} margin
136
+ * @returns {number}
137
+ */
138
+ export const normalizedCollRatio = (quote, compoundedInterest, margin) => {
139
+ const amountIn = getAmountIn(quote).value;
140
+ const amountOut = getAmountOut(quote).value;
141
+ const interestNumerator = compoundedInterest.numerator.value;
142
+ const interestBase = compoundedInterest.denominator.value;
143
+ const numerator = multiply(
144
+ margin.numerator.value,
145
+ multiply(amountIn, interestNumerator),
146
+ );
147
+ const denominator = multiply(
148
+ amountOut,
149
+ multiply(interestBase, margin.denominator.value),
150
+ );
151
+
152
+ return Number(numerator) / Number(denominator);
153
+ };
154
+ harden(normalizedCollRatio);
155
+
156
+ /**
157
+ * Create a sort key for a normalized collateralization ratio. We want the key
158
+ * to be based on a float with as much resolution as we can get, so we multiply
159
+ * out the numerator and the denominator, and divide only once.
160
+ *
161
+ * @param {PriceQuote} quote
162
+ * @param {Ratio} compoundedInterest
163
+ * @param {Ratio} margin
164
+ * @returns {string} lexically sortable string in which highest
165
+ * debt-to-collateral is earliest
166
+ */
167
+ export const normalizedCollRatioKey = (quote, compoundedInterest, margin) => {
168
+ const collRatio = normalizedCollRatio(quote, compoundedInterest, margin);
169
+ return `${encodeNumber(collRatio)}:`;
170
+ };
171
+ harden(normalizedCollRatioKey);
@@ -1,2 +1,4 @@
1
+ // @jessie-check
2
+
1
3
  import '@agoric/zoe/exported.js';
2
4
  import './types.js';