@indigo-labs/indigo-sdk 0.5.4 → 0.5.6

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 (208) hide show
  1. package/dist/index.d.mts +11 -1
  2. package/dist/index.d.ts +11 -1
  3. package/dist/index.js +17 -0
  4. package/dist/index.mjs +15 -0
  5. package/package.json +11 -1
  6. package/.claude/settings.local.json +0 -7
  7. package/.github/workflows/ci.yml +0 -66
  8. package/.husky/pre-commit +0 -1
  9. package/.nvmrc +0 -1
  10. package/.prettierignore +0 -1
  11. package/.prettierrc +0 -6
  12. package/eslint.config.mjs +0 -42
  13. package/scripts/bench.sh +0 -62
  14. package/scripts/run-repeat.sh +0 -22
  15. package/src/contracts/cdp/helpers.ts +0 -173
  16. package/src/contracts/cdp/scripts.ts +0 -70
  17. package/src/contracts/cdp/transactions.ts +0 -1584
  18. package/src/contracts/cdp/types-new.ts +0 -277
  19. package/src/contracts/cdp/types.ts +0 -43
  20. package/src/contracts/cdp-creator/queries.ts +0 -30
  21. package/src/contracts/cdp-creator/scripts.ts +0 -45
  22. package/src/contracts/cdp-creator/types-new.ts +0 -50
  23. package/src/contracts/cdp-creator/types.ts +0 -24
  24. package/src/contracts/collector/scripts.ts +0 -32
  25. package/src/contracts/collector/transactions.ts +0 -50
  26. package/src/contracts/collector/types-new.ts +0 -17
  27. package/src/contracts/execute/scripts.ts +0 -57
  28. package/src/contracts/execute/types-new.ts +0 -44
  29. package/src/contracts/execute/types.ts +0 -24
  30. package/src/contracts/gov/helpers.ts +0 -351
  31. package/src/contracts/gov/scripts.ts +0 -41
  32. package/src/contracts/gov/transactions.ts +0 -1607
  33. package/src/contracts/gov/types-new.ts +0 -268
  34. package/src/contracts/gov/types.ts +0 -22
  35. package/src/contracts/iasset/helpers.ts +0 -170
  36. package/src/contracts/iasset/queries.ts +0 -102
  37. package/src/contracts/iasset/scripts.ts +0 -38
  38. package/src/contracts/iasset/types.ts +0 -154
  39. package/src/contracts/initialize/actions.ts +0 -789
  40. package/src/contracts/initialize/helpers.ts +0 -616
  41. package/src/contracts/initialize/types.ts +0 -116
  42. package/src/contracts/interest-collection/helpers.ts +0 -19
  43. package/src/contracts/interest-collection/queries.ts +0 -66
  44. package/src/contracts/interest-collection/scripts.ts +0 -44
  45. package/src/contracts/interest-collection/transactions.ts +0 -433
  46. package/src/contracts/interest-collection/types-new.ts +0 -50
  47. package/src/contracts/interest-collection/types.ts +0 -26
  48. package/src/contracts/interest-oracle/helpers.ts +0 -61
  49. package/src/contracts/interest-oracle/scripts.ts +0 -18
  50. package/src/contracts/interest-oracle/transactions.ts +0 -151
  51. package/src/contracts/interest-oracle/types-new.ts +0 -32
  52. package/src/contracts/interest-oracle/types.ts +0 -16
  53. package/src/contracts/one-shot/scripts.ts +0 -12
  54. package/src/contracts/one-shot/transactions.ts +0 -66
  55. package/src/contracts/one-shot/types.ts +0 -22
  56. package/src/contracts/poll/helpers.ts +0 -37
  57. package/src/contracts/poll/scripts.ts +0 -71
  58. package/src/contracts/poll/types-poll-manager.ts +0 -20
  59. package/src/contracts/poll/types-poll-new.ts +0 -196
  60. package/src/contracts/poll/types-poll-shard.ts +0 -16
  61. package/src/contracts/price-oracle/helpers.ts +0 -30
  62. package/src/contracts/price-oracle/scripts.ts +0 -18
  63. package/src/contracts/price-oracle/transactions.ts +0 -115
  64. package/src/contracts/price-oracle/types-new.ts +0 -50
  65. package/src/contracts/price-oracle/types.ts +0 -16
  66. package/src/contracts/pyth-feed/helpers.ts +0 -82
  67. package/src/contracts/pyth-feed/scripts.ts +0 -15
  68. package/src/contracts/pyth-feed/types.ts +0 -181
  69. package/src/contracts/rob/helpers.ts +0 -666
  70. package/src/contracts/rob/scripts.ts +0 -35
  71. package/src/contracts/rob/transactions.ts +0 -423
  72. package/src/contracts/rob/types-new.ts +0 -128
  73. package/src/contracts/rob/types.ts +0 -16
  74. package/src/contracts/rob-leverage/helpers.ts +0 -422
  75. package/src/contracts/rob-leverage/transactions.ts +0 -368
  76. package/src/contracts/stability-pool/helpers.ts +0 -798
  77. package/src/contracts/stability-pool/queries.ts +0 -132
  78. package/src/contracts/stability-pool/scripts.ts +0 -51
  79. package/src/contracts/stability-pool/transactions.ts +0 -921
  80. package/src/contracts/stability-pool/types-new.ts +0 -385
  81. package/src/contracts/stability-pool/types.ts +0 -25
  82. package/src/contracts/stableswap/helpers.ts +0 -507
  83. package/src/contracts/stableswap/scripts.ts +0 -37
  84. package/src/contracts/stableswap/transactions.ts +0 -475
  85. package/src/contracts/stableswap/types-new.ts +0 -131
  86. package/src/contracts/stableswap/types.ts +0 -17
  87. package/src/contracts/staking/helpers.ts +0 -136
  88. package/src/contracts/staking/scripts.ts +0 -41
  89. package/src/contracts/staking/transactions.ts +0 -349
  90. package/src/contracts/staking/types-new.ts +0 -137
  91. package/src/contracts/staking/types.ts +0 -17
  92. package/src/contracts/treasury/helpers.ts +0 -21
  93. package/src/contracts/treasury/queries.ts +0 -100
  94. package/src/contracts/treasury/scripts.ts +0 -27
  95. package/src/contracts/treasury/transactions.ts +0 -334
  96. package/src/contracts/treasury/types-new.ts +0 -69
  97. package/src/contracts/treasury/types.ts +0 -14
  98. package/src/contracts/version-registry/scripts.ts +0 -29
  99. package/src/contracts/version-registry/types-new.ts +0 -18
  100. package/src/contracts/version-registry/types.ts +0 -17
  101. package/src/index.ts +0 -93
  102. package/src/scripts/always-fail-validator.ts +0 -7
  103. package/src/scripts/auth-token-policy.ts +0 -24
  104. package/src/scripts/iasset-policy.ts +0 -23
  105. package/src/types/evolution-schema-options.ts +0 -16
  106. package/src/types/generic.ts +0 -52
  107. package/src/types/multisig.ts +0 -48
  108. package/src/types/on-chain-decimal.ts +0 -57
  109. package/src/types/rational.ts +0 -61
  110. package/src/types/system-params.ts +0 -463
  111. package/src/utils/array-utils.ts +0 -108
  112. package/src/utils/bigint-utils.ts +0 -35
  113. package/src/utils/helper-txs.ts +0 -31
  114. package/src/utils/indigo-helpers.ts +0 -17
  115. package/src/utils/lucid-utils.ts +0 -125
  116. package/src/utils/oracle-helpers.ts +0 -62
  117. package/src/utils/pyth/decode.ts +0 -223
  118. package/src/utils/pyth/encode.ts +0 -262
  119. package/src/utils/pyth/index.ts +0 -14
  120. package/src/utils/pyth/types.ts +0 -87
  121. package/src/utils/time-helpers.ts +0 -4
  122. package/src/utils/utils.ts +0 -25
  123. package/src/validators/always-succeed-validator.ts +0 -6
  124. package/src/validators/cdp-creator-validator.ts +0 -7
  125. package/src/validators/cdp-redeem-validator.ts +0 -7
  126. package/src/validators/cdp-validator.ts +0 -7
  127. package/src/validators/collector-validator.ts +0 -7
  128. package/src/validators/execute-validator.ts +0 -7
  129. package/src/validators/governance-validator.ts +0 -7
  130. package/src/validators/iasset-validator.ts +0 -7
  131. package/src/validators/interest-collection-validator.ts +0 -7
  132. package/src/validators/interest-oracle-validator.ts +0 -7
  133. package/src/validators/one-shot-policy.ts +0 -7
  134. package/src/validators/poll-manager-validator.ts +0 -7
  135. package/src/validators/poll-shard-validator.ts +0 -7
  136. package/src/validators/price-oracle-validator.ts +0 -7
  137. package/src/validators/pyth-feed-validator.ts +0 -7
  138. package/src/validators/rob-validator.ts +0 -7
  139. package/src/validators/stability-pool-validator.ts +0 -7
  140. package/src/validators/stableswap-validator.ts +0 -7
  141. package/src/validators/staking-validator.ts +0 -7
  142. package/src/validators/treasury-validator.ts +0 -7
  143. package/src/validators/version-record-policy.ts +0 -7
  144. package/src/validators/version-registry-validator.ts +0 -7
  145. package/tests/always-succeed/script.ts +0 -7
  146. package/tests/array-utils.test.ts +0 -92
  147. package/tests/bigint-utils.test.ts +0 -41
  148. package/tests/cdp/actions.ts +0 -680
  149. package/tests/cdp/cdp-helpers.ts +0 -55
  150. package/tests/cdp/cdp-queries.ts +0 -423
  151. package/tests/cdp/cdp.test.ts +0 -6730
  152. package/tests/cdp/transactions-mutated.ts +0 -1733
  153. package/tests/data/system-params.json +0 -1155
  154. package/tests/datums.test.ts +0 -302
  155. package/tests/endpoints/initialize.ts +0 -78
  156. package/tests/endpoints/interest-collector.ts +0 -37
  157. package/tests/endpoints/treasury.ts +0 -70
  158. package/tests/gov/actions.ts +0 -381
  159. package/tests/gov/gov.test.ts +0 -5147
  160. package/tests/gov/governance-queries.ts +0 -37
  161. package/tests/hash-checks.test.ts +0 -112
  162. package/tests/indigo-test-helpers.ts +0 -99
  163. package/tests/initialize.test.ts +0 -79
  164. package/tests/interest-calculations.test.ts +0 -120
  165. package/tests/interest-collection/interest-collection.test.ts +0 -843
  166. package/tests/interest-collection/transactions-mutated.ts +0 -260
  167. package/tests/interest-oracle.test.ts +0 -93
  168. package/tests/mock/assets-mock.ts +0 -243
  169. package/tests/mock/protocol-params-mock.ts +0 -21
  170. package/tests/price-oracle/actions.ts +0 -161
  171. package/tests/price-oracle/price-oracle-queries.ts +0 -12
  172. package/tests/price-oracle/price-oracle.test.ts +0 -228
  173. package/tests/price-oracle/transactions-mutated.ts +0 -59
  174. package/tests/pyth/endpoints.ts +0 -96
  175. package/tests/pyth/helpers.ts +0 -37
  176. package/tests/pyth/pyth-encoding.test.ts +0 -376
  177. package/tests/pyth/pyth-feeds.test.ts +0 -943
  178. package/tests/pyth/pyth-indigo.test.ts +0 -505
  179. package/tests/pyth/pyth.test.ts +0 -299
  180. package/tests/queries/collector-queries.ts +0 -27
  181. package/tests/queries/execute-queries.ts +0 -47
  182. package/tests/queries/iasset-queries.ts +0 -149
  183. package/tests/queries/interest-oracle-queries.ts +0 -12
  184. package/tests/queries/poll-queries.ts +0 -97
  185. package/tests/queries/staking-queries.ts +0 -54
  186. package/tests/rob/actions.ts +0 -56
  187. package/tests/rob/rob-leverage.test.ts +0 -2555
  188. package/tests/rob/rob-queries.ts +0 -95
  189. package/tests/rob/rob.test.ts +0 -3677
  190. package/tests/rob/transactions-mutated.ts +0 -844
  191. package/tests/script-size.test.ts +0 -240
  192. package/tests/setup.ts +0 -135
  193. package/tests/stability-pool/actions.ts +0 -229
  194. package/tests/stability-pool.test.ts +0 -6491
  195. package/tests/stableswap/stableswap-actions.ts +0 -83
  196. package/tests/stableswap/stableswap-queries.ts +0 -98
  197. package/tests/stableswap/stableswap.test.ts +0 -4471
  198. package/tests/stableswap/transactions-mutated.ts +0 -348
  199. package/tests/staking.test.ts +0 -172
  200. package/tests/test-helpers.ts +0 -94
  201. package/tests/treasury/actions.ts +0 -67
  202. package/tests/treasury/treasury.test.ts +0 -320
  203. package/tests/utils/asserts.ts +0 -87
  204. package/tests/utils/benchmark-utils.ts +0 -130
  205. package/tests/utils/index.ts +0 -168
  206. package/tsconfig.build.json +0 -4
  207. package/tsconfig.json +0 -27
  208. package/vitest.config.ts +0 -11
@@ -1,2555 +0,0 @@
1
- import { beforeEach, describe, expect, test, vi } from 'vitest';
2
- import {
3
- addrDetails,
4
- calculateLeverageFromCollateralRatio,
5
- calculateTotalCollateralForRedemption,
6
- cdpCollateralRatioPercentage,
7
- fromSystemParamsAsset,
8
- getInlineDatumOrThrow,
9
- leverageCdpWithRob,
10
- MAX_REDEMPTIONS_WITH_CDP_OPEN,
11
- MIN_ROB_COLLATERAL_AMT,
12
- openRob,
13
- randomRobsSubsetSatisfyingTargetCollateral,
14
- Rational,
15
- rationalToFloat,
16
- robCollateralAmtToSpend,
17
- RobDatum,
18
- SystemParams,
19
- } from '../../src';
20
- import {
21
- addAssets,
22
- Assets,
23
- Emulator,
24
- EmulatorAccount,
25
- fromHex,
26
- fromText,
27
- generateEmulatorAccount,
28
- Lucid,
29
- toHex,
30
- UTxO,
31
- } from '@lucid-evolution/lucid';
32
- import { LucidContext, runAndAwaitTx } from '../test-helpers';
33
-
34
- import { init } from '../endpoints/initialize';
35
- import {
36
- DEFAULT_PRICE,
37
- iusdInitialAssetCfg,
38
- iusdInitialAssetCfgWithPyth,
39
- mkBaseCollateralAsset,
40
- } from '../mock/assets-mock';
41
- import { assertValueInRange } from '../utils/asserts';
42
-
43
- import {
44
- adaAssetClass,
45
- AssetClass,
46
- assetClassToUnit,
47
- assetClassValueOf,
48
- isSameAssetClass,
49
- lovelacesAmt,
50
- mkAssetsOf,
51
- mkLovelacesOf,
52
- } from '@3rd-eye-labs/cardano-offchain-common';
53
- import {
54
- findAllNecessaryOrefs,
55
- findCdp,
56
- findPriceOracleFromCollateralAsset,
57
- } from '../cdp/cdp-queries';
58
- import { parsePriceOracleDatum } from '../../src/contracts/price-oracle/types-new';
59
- import { parseInterestOracleDatum } from '../../src/contracts/interest-oracle/types-new';
60
- import { benchmarkAndAwaitTx } from '../utils/benchmark-utils';
61
- import { findAllRobs } from './rob-queries';
62
- import { MAINNET_PROTOCOL_PARAMETERS } from '../indigo-test-helpers';
63
- import { match, P } from 'ts-pattern';
64
- import { ParsedFeedPayload } from '@pythnetwork/pyth-lazer-sdk';
65
- import { createPythMessage } from '../pyth/helpers';
66
- import { retrieveAdjustedPrice } from '../../src/utils/oracle-helpers';
67
-
68
- type MyContext = LucidContext<{
69
- admin: EmulatorAccount;
70
- user: EmulatorAccount;
71
- }>;
72
-
73
- const collateralAssetA: AssetClass = {
74
- currencySymbol: fromHex(
75
- // random generated
76
- 'cc072059ae741791b7b9c23d9baea6a0b0d764dec617ce7e027a8dea',
77
- ),
78
- tokenName: fromHex(fromText('A')),
79
- };
80
-
81
- async function openBuyRobs(
82
- context: MyContext,
83
- sysParams: SystemParams,
84
- iasset: string,
85
- collateralAsset: AssetClass,
86
- amountsToSpend: bigint[],
87
- maxPrice: Rational,
88
- ): Promise<void> {
89
- for (const amt of amountsToSpend) {
90
- await runAndAwaitTx(
91
- context.lucid,
92
- openRob(
93
- iasset,
94
- amt,
95
- { BuyIAssetOrder: { collateralAsset: collateralAsset, maxPrice } },
96
- context.lucid,
97
- sysParams,
98
- ),
99
- );
100
- }
101
- }
102
-
103
- function hadRobRedemption(
104
- lrp: { utxo: UTxO; datum: RobDatum },
105
- sysParams: SystemParams,
106
- ): boolean {
107
- return (
108
- assetClassValueOf(lrp.utxo.assets, {
109
- currencySymbol: fromHex(
110
- sysParams.cdpParams.cdpAssetSymbol.unCurrencySymbol,
111
- ),
112
- tokenName: lrp.datum.iasset,
113
- }) > 0
114
- );
115
- }
116
-
117
- describe('randomRobsSubsetSatisfyingTargetCollateral', () => {
118
- const mockUtxo = (ada: bigint, otherAssets: Assets = {}): UTxO => ({
119
- address: '',
120
- assets: addAssets(mkLovelacesOf(ada), otherAssets),
121
- outputIndex: 0,
122
- txHash: '',
123
- });
124
-
125
- test('1', () => {
126
- const lrps: [UTxO, RobDatum][] = [
127
- [
128
- mockUtxo(100_000_000n),
129
- {
130
- iasset: fromHex(fromText('iUSD')),
131
- orderType: {
132
- BuyIAssetOrder: {
133
- collateralAsset: adaAssetClass,
134
- maxPrice: { numerator: 1n, denominator: 1n },
135
- },
136
- },
137
- owner: fromHex(''),
138
- robRefInput: { outputIndex: 0n, txHash: fromHex('') },
139
- },
140
- ],
141
- [
142
- mockUtxo(100_000_000n),
143
- {
144
- iasset: fromHex(fromText('iUSD')),
145
- orderType: {
146
- BuyIAssetOrder: {
147
- collateralAsset: adaAssetClass,
148
- maxPrice: { numerator: 1n, denominator: 1n },
149
- },
150
- },
151
- owner: fromHex(''),
152
- robRefInput: { outputIndex: 0n, txHash: fromHex('') },
153
- },
154
- ],
155
- ];
156
-
157
- expect(
158
- randomRobsSubsetSatisfyingTargetCollateral(
159
- fromHex(fromText('iUSD')),
160
- adaAssetClass,
161
- 120_000_000n,
162
- { numerator: 1n, denominator: 1n },
163
- lrps,
164
- MAX_REDEMPTIONS_WITH_CDP_OPEN,
165
- ),
166
- ).toEqual(expect.arrayContaining(lrps));
167
- });
168
-
169
- test('2', () => {
170
- const lrps: [UTxO, RobDatum][] = [
171
- [
172
- mockUtxo(150_000_000n),
173
- {
174
- iasset: fromHex(fromText('iUSD')),
175
- orderType: {
176
- BuyIAssetOrder: {
177
- collateralAsset: adaAssetClass,
178
- maxPrice: { numerator: 1n, denominator: 1n },
179
- },
180
- },
181
- owner: fromHex(''),
182
- robRefInput: { outputIndex: 0n, txHash: fromHex('') },
183
- },
184
- ],
185
- ];
186
-
187
- expect(
188
- randomRobsSubsetSatisfyingTargetCollateral(
189
- fromHex(fromText('iUSD')),
190
- adaAssetClass,
191
- 100_000_000n,
192
- { numerator: 1n, denominator: 1n },
193
- lrps,
194
- MAX_REDEMPTIONS_WITH_CDP_OPEN,
195
- ),
196
- ).toEqual(lrps);
197
- });
198
-
199
- test('3', () => {
200
- const lrps: [UTxO, RobDatum][] = [
201
- [
202
- mockUtxo(100_000_000n),
203
- {
204
- iasset: fromHex(fromText('iUSD')),
205
- orderType: {
206
- BuyIAssetOrder: {
207
- collateralAsset: adaAssetClass,
208
- maxPrice: { numerator: 1n, denominator: 1n },
209
- },
210
- },
211
- owner: fromHex(''),
212
- robRefInput: { outputIndex: 0n, txHash: fromHex('') },
213
- },
214
- ],
215
- [
216
- mockUtxo(10_000_000n),
217
- {
218
- iasset: fromHex(fromText('iUSD')),
219
- orderType: {
220
- BuyIAssetOrder: {
221
- collateralAsset: adaAssetClass,
222
- maxPrice: { numerator: 1n, denominator: 1n },
223
- },
224
- },
225
- owner: fromHex(''),
226
- robRefInput: { outputIndex: 0n, txHash: fromHex('') },
227
- },
228
- ],
229
- [
230
- mockUtxo(100_000_000n),
231
- {
232
- iasset: fromHex(fromText('iUSD')),
233
- orderType: {
234
- BuyIAssetOrder: {
235
- collateralAsset: adaAssetClass,
236
- maxPrice: { numerator: 1n, denominator: 1n },
237
- },
238
- },
239
- owner: fromHex(''),
240
- robRefInput: { outputIndex: 0n, txHash: fromHex('') },
241
- },
242
- ],
243
- ];
244
-
245
- const mockedShuffle = vi.fn().mockImplementation(() => lrps);
246
-
247
- expect(
248
- randomRobsSubsetSatisfyingTargetCollateral(
249
- fromHex(fromText('iUSD')),
250
- adaAssetClass,
251
- 120_000_000n,
252
- { numerator: 1n, denominator: 1n },
253
- lrps,
254
- MAX_REDEMPTIONS_WITH_CDP_OPEN,
255
- mockedShuffle,
256
- ),
257
- ).toEqual(expect.arrayContaining(lrps));
258
- });
259
-
260
- test('4 (min rob collateral causes less redeemable)', () => {
261
- const lrps: [UTxO, RobDatum][] = [
262
- [
263
- mockUtxo(100_000_000n),
264
- {
265
- iasset: fromHex(fromText('iUSD')),
266
- orderType: {
267
- BuyIAssetOrder: {
268
- collateralAsset: adaAssetClass,
269
- maxPrice: { numerator: 1n, denominator: 1n },
270
- },
271
- },
272
- owner: fromHex(''),
273
- robRefInput: { outputIndex: 0n, txHash: fromHex('') },
274
- },
275
- ],
276
- ];
277
-
278
- const mockedShuffle = vi.fn().mockImplementation(() => lrps);
279
-
280
- expect(() =>
281
- randomRobsSubsetSatisfyingTargetCollateral(
282
- fromHex(fromText('iUSD')),
283
- adaAssetClass,
284
- 100_000_000n,
285
- { numerator: 1n, denominator: 1n },
286
- lrps,
287
- MAX_REDEMPTIONS_WITH_CDP_OPEN,
288
- mockedShuffle,
289
- ),
290
- ).toThrow(new Error("Couldn't achieve target lovelaces"));
291
- });
292
-
293
- test('5 (too small amount to redeem - payout 0)', () => {
294
- const lrps: [UTxO, RobDatum][] = [
295
- [
296
- mockUtxo(100_000_000n),
297
- {
298
- iasset: fromHex(fromText('iUSD')),
299
- orderType: {
300
- BuyIAssetOrder: {
301
- collateralAsset: adaAssetClass,
302
- maxPrice: { numerator: 1n, denominator: 1n },
303
- },
304
- },
305
- owner: fromHex(''),
306
- robRefInput: { outputIndex: 0n, txHash: fromHex('') },
307
- },
308
- ],
309
- ];
310
-
311
- expect(() =>
312
- randomRobsSubsetSatisfyingTargetCollateral(
313
- fromHex(fromText('iUSD')),
314
- adaAssetClass,
315
- 5n,
316
- { numerator: 10n, denominator: 1n },
317
- lrps,
318
- MAX_REDEMPTIONS_WITH_CDP_OPEN,
319
- ),
320
- ).toThrow('Must redeem and payout more than 0.');
321
- });
322
-
323
- test('6 (too small amount to redeem - redeemable 0)', () => {
324
- const lrps: [UTxO, RobDatum][] = [
325
- [
326
- mockUtxo(100_000_000n),
327
- {
328
- iasset: fromHex(fromText('iUSD')),
329
- orderType: {
330
- BuyIAssetOrder: {
331
- collateralAsset: adaAssetClass,
332
- maxPrice: { numerator: 1n, denominator: 1n },
333
- },
334
- },
335
- owner: fromHex(''),
336
- robRefInput: { outputIndex: 0n, txHash: fromHex('') },
337
- },
338
- ],
339
- ];
340
-
341
- expect(() =>
342
- randomRobsSubsetSatisfyingTargetCollateral(
343
- fromHex(fromText('iUSD')),
344
- adaAssetClass,
345
- 0n,
346
- { numerator: 1n, denominator: 1n },
347
- lrps,
348
- MAX_REDEMPTIONS_WITH_CDP_OPEN,
349
- ),
350
- ).toThrow('Must redeem and payout more than 0.');
351
- });
352
-
353
- test('7 (dont pick fully redeemed rob)', () => {
354
- const lrps: [UTxO, RobDatum][] = [
355
- [
356
- mockUtxo(5n + MIN_ROB_COLLATERAL_AMT),
357
- {
358
- iasset: fromHex(fromText('iUSD')),
359
- orderType: {
360
- BuyIAssetOrder: {
361
- collateralAsset: adaAssetClass,
362
- maxPrice: { numerator: 20n, denominator: 1n },
363
- },
364
- },
365
- owner: fromHex(''),
366
- robRefInput: { outputIndex: 0n, txHash: fromHex('') },
367
- },
368
- ],
369
- [
370
- mockUtxo(100_000_000n),
371
- {
372
- iasset: fromHex(fromText('iUSD')),
373
- orderType: {
374
- BuyIAssetOrder: {
375
- collateralAsset: adaAssetClass,
376
- maxPrice: { numerator: 1n, denominator: 1n },
377
- },
378
- },
379
- owner: fromHex(''),
380
- robRefInput: { outputIndex: 0n, txHash: fromHex('') },
381
- },
382
- ],
383
- ];
384
-
385
- const mockedShuffle = vi.fn().mockImplementation(() => lrps);
386
-
387
- expect(
388
- randomRobsSubsetSatisfyingTargetCollateral(
389
- fromHex(fromText('iUSD')),
390
- adaAssetClass,
391
- 100_000n,
392
- { numerator: 10n, denominator: 1n },
393
- lrps,
394
- MAX_REDEMPTIONS_WITH_CDP_OPEN,
395
- mockedShuffle,
396
- ),
397
- ).toEqual(expect.arrayContaining([lrps[1]]));
398
- });
399
-
400
- test('8 (prevent redeeming 0 or payout 0 to any ROB)', () => {
401
- const lrps: [UTxO, RobDatum][] = [
402
- [
403
- mockUtxo(100n + MIN_ROB_COLLATERAL_AMT),
404
- {
405
- iasset: fromHex(fromText('iUSD')),
406
- orderType: {
407
- BuyIAssetOrder: {
408
- collateralAsset: adaAssetClass,
409
- maxPrice: { numerator: 20n, denominator: 1n },
410
- },
411
- },
412
- owner: fromHex(''),
413
- robRefInput: { outputIndex: 0n, txHash: fromHex('') },
414
- },
415
- ],
416
- [
417
- mockUtxo(10n + MIN_ROB_COLLATERAL_AMT),
418
- {
419
- iasset: fromHex(fromText('iUSD')),
420
- orderType: {
421
- BuyIAssetOrder: {
422
- collateralAsset: adaAssetClass,
423
- maxPrice: { numerator: 20n, denominator: 1n },
424
- },
425
- },
426
- owner: fromHex(''),
427
- robRefInput: { outputIndex: 0n, txHash: fromHex('') },
428
- },
429
- ],
430
- [
431
- mockUtxo(30n + MIN_ROB_COLLATERAL_AMT),
432
- {
433
- iasset: fromHex(fromText('iUSD')),
434
- orderType: {
435
- BuyIAssetOrder: {
436
- collateralAsset: adaAssetClass,
437
- maxPrice: { numerator: 20n, denominator: 1n },
438
- },
439
- },
440
- owner: fromHex(''),
441
- robRefInput: { outputIndex: 0n, txHash: fromHex('') },
442
- },
443
- ],
444
- ];
445
-
446
- const mockedShuffle = vi.fn().mockImplementation(() => lrps);
447
-
448
- // Since the second ROB would cause the target redeemable unachievable because otherwise,
449
- // the remaining ROB would payout 0.
450
- // Since there's a larger ROB, replace the second one with the last one achieving the target in full.
451
- expect(
452
- randomRobsSubsetSatisfyingTargetCollateral(
453
- fromHex(fromText('iUSD')),
454
- adaAssetClass,
455
- 115n,
456
- { numerator: 10n, denominator: 1n },
457
- lrps,
458
- MAX_REDEMPTIONS_WITH_CDP_OPEN,
459
- mockedShuffle,
460
- ),
461
- ).toEqual(expect.arrayContaining([lrps[0], lrps[2]]));
462
- });
463
-
464
- test('9 (cant redeem more to achieve target because it would cause 0 payout)', () => {
465
- const lrps: [UTxO, RobDatum][] = [
466
- [
467
- mockUtxo(100n + MIN_ROB_COLLATERAL_AMT),
468
- {
469
- iasset: fromHex(fromText('iUSD')),
470
- orderType: {
471
- BuyIAssetOrder: {
472
- collateralAsset: adaAssetClass,
473
- maxPrice: { numerator: 20n, denominator: 1n },
474
- },
475
- },
476
- owner: fromHex(''),
477
- robRefInput: { outputIndex: 0n, txHash: fromHex('') },
478
- },
479
- ],
480
- [
481
- mockUtxo(100n + MIN_ROB_COLLATERAL_AMT),
482
- {
483
- iasset: fromHex(fromText('iUSD')),
484
- orderType: {
485
- BuyIAssetOrder: {
486
- collateralAsset: adaAssetClass,
487
- maxPrice: { numerator: 20n, denominator: 1n },
488
- },
489
- },
490
- owner: fromHex(''),
491
- robRefInput: { outputIndex: 0n, txHash: fromHex('') },
492
- },
493
- ],
494
- ];
495
-
496
- const mockedShuffle = vi.fn().mockImplementation(() => lrps);
497
-
498
- expect(
499
- randomRobsSubsetSatisfyingTargetCollateral(
500
- fromHex(fromText('iUSD')),
501
- adaAssetClass,
502
- 105n,
503
- { numerator: 10n, denominator: 1n },
504
- lrps,
505
- MAX_REDEMPTIONS_WITH_CDP_OPEN,
506
- mockedShuffle,
507
- ),
508
- ).toEqual(expect.arrayContaining([lrps[0]]));
509
- });
510
-
511
- test('filtering by iasset 1', () => {
512
- const lrps: [UTxO, RobDatum][] = [
513
- [
514
- mockUtxo(100_000_000n),
515
- {
516
- iasset: fromHex(fromText('iUSD')),
517
- orderType: {
518
- BuyIAssetOrder: {
519
- collateralAsset: adaAssetClass,
520
- maxPrice: { numerator: 1n, denominator: 1n },
521
- },
522
- },
523
- owner: fromHex(''),
524
- robRefInput: { outputIndex: 0n, txHash: fromHex('') },
525
- },
526
- ],
527
- [
528
- mockUtxo(100_000_000n),
529
- {
530
- iasset: fromHex(fromText('iBTC')),
531
- orderType: {
532
- BuyIAssetOrder: {
533
- collateralAsset: adaAssetClass,
534
- maxPrice: { numerator: 1n, denominator: 1n },
535
- },
536
- },
537
- owner: fromHex(''),
538
- robRefInput: { outputIndex: 0n, txHash: fromHex('') },
539
- },
540
- ],
541
- [
542
- mockUtxo(100_000_000n),
543
- {
544
- iasset: fromHex(fromText('iUSD')),
545
- orderType: {
546
- BuyIAssetOrder: {
547
- collateralAsset: adaAssetClass,
548
- maxPrice: { numerator: 1n, denominator: 1n },
549
- },
550
- },
551
- owner: fromHex(''),
552
- robRefInput: { outputIndex: 0n, txHash: fromHex('') },
553
- },
554
- ],
555
- ];
556
-
557
- expect(
558
- randomRobsSubsetSatisfyingTargetCollateral(
559
- fromHex(fromText('iUSD')),
560
- adaAssetClass,
561
- 110_000_000n,
562
- { numerator: 1n, denominator: 1n },
563
- lrps,
564
- MAX_REDEMPTIONS_WITH_CDP_OPEN,
565
- ),
566
- ).toEqual(expect.arrayContaining([lrps[0], lrps[2]]));
567
- });
568
-
569
- test('filtering by iasset 2', () => {
570
- const lrps: [UTxO, RobDatum][] = [
571
- [
572
- mockUtxo(100_000_000n),
573
- {
574
- iasset: fromHex(fromText('iUSD')),
575
- orderType: {
576
- BuyIAssetOrder: {
577
- collateralAsset: adaAssetClass,
578
- maxPrice: { numerator: 1n, denominator: 1n },
579
- },
580
- },
581
- owner: fromHex(''),
582
- robRefInput: { outputIndex: 0n, txHash: fromHex('') },
583
- },
584
- ],
585
- [
586
- mockUtxo(100_000_000n),
587
- {
588
- iasset: fromHex(fromText('iBTC')),
589
- orderType: {
590
- BuyIAssetOrder: {
591
- collateralAsset: adaAssetClass,
592
- maxPrice: { numerator: 1n, denominator: 1n },
593
- },
594
- },
595
- owner: fromHex(''),
596
- robRefInput: { outputIndex: 0n, txHash: fromHex('') },
597
- },
598
- ],
599
- ];
600
-
601
- expect(() =>
602
- randomRobsSubsetSatisfyingTargetCollateral(
603
- fromHex(fromText('iUSD')),
604
- adaAssetClass,
605
- 110_000_000n,
606
- { numerator: 1n, denominator: 1n },
607
- lrps,
608
- MAX_REDEMPTIONS_WITH_CDP_OPEN,
609
- ),
610
- ).toThrow("Couldn't achieve target lovelaces");
611
- });
612
-
613
- test('filtering by collateral asset 1', () => {
614
- const lrps: [UTxO, RobDatum][] = [
615
- [
616
- mockUtxo(100_000_000n, mkAssetsOf(collateralAssetA, 100n)),
617
- {
618
- iasset: fromHex(fromText('iUSD')),
619
- orderType: {
620
- BuyIAssetOrder: {
621
- collateralAsset: collateralAssetA,
622
- maxPrice: { numerator: 1n, denominator: 1n },
623
- },
624
- },
625
- owner: fromHex(''),
626
- robRefInput: { outputIndex: 0n, txHash: fromHex('') },
627
- },
628
- ],
629
- [
630
- mockUtxo(100_000_000n),
631
- {
632
- iasset: fromHex(fromText('iUSD')),
633
- orderType: {
634
- BuyIAssetOrder: {
635
- collateralAsset: adaAssetClass,
636
- maxPrice: { numerator: 1n, denominator: 1n },
637
- },
638
- },
639
- owner: fromHex(''),
640
- robRefInput: { outputIndex: 0n, txHash: fromHex('') },
641
- },
642
- ],
643
- [
644
- mockUtxo(100_000_000n),
645
- {
646
- iasset: fromHex(fromText('iBTC')),
647
- orderType: {
648
- BuyIAssetOrder: {
649
- collateralAsset: adaAssetClass,
650
- maxPrice: { numerator: 1n, denominator: 1n },
651
- },
652
- },
653
- owner: fromHex(''),
654
- robRefInput: { outputIndex: 0n, txHash: fromHex('') },
655
- },
656
- ],
657
- [
658
- mockUtxo(100_000_000n, mkAssetsOf(collateralAssetA, 100n)),
659
- {
660
- iasset: fromHex(fromText('iUSD')),
661
- orderType: {
662
- BuyIAssetOrder: {
663
- collateralAsset: collateralAssetA,
664
- maxPrice: { numerator: 1n, denominator: 1n },
665
- },
666
- },
667
- owner: fromHex(''),
668
- robRefInput: { outputIndex: 0n, txHash: fromHex('') },
669
- },
670
- ],
671
- ];
672
-
673
- expect(
674
- randomRobsSubsetSatisfyingTargetCollateral(
675
- fromHex(fromText('iUSD')),
676
- collateralAssetA,
677
- 110n,
678
- { numerator: 1n, denominator: 1n },
679
- lrps,
680
- MAX_REDEMPTIONS_WITH_CDP_OPEN,
681
- ),
682
- ).toEqual(expect.arrayContaining([lrps[0], lrps[3]]));
683
- });
684
-
685
- test('filtering by collateral asset 2', () => {
686
- const lrps: [UTxO, RobDatum][] = [
687
- [
688
- mockUtxo(100n),
689
- {
690
- iasset: fromHex(fromText('iUSD')),
691
- orderType: {
692
- BuyIAssetOrder: {
693
- collateralAsset: adaAssetClass,
694
- maxPrice: { numerator: 1n, denominator: 1n },
695
- },
696
- },
697
- owner: fromHex(''),
698
- robRefInput: { outputIndex: 0n, txHash: fromHex('') },
699
- },
700
- ],
701
- [
702
- mockUtxo(100n),
703
- {
704
- iasset: fromHex(fromText('iUSD')),
705
- orderType: {
706
- BuyIAssetOrder: {
707
- collateralAsset: adaAssetClass,
708
- maxPrice: { numerator: 1n, denominator: 1n },
709
- },
710
- },
711
- owner: fromHex(''),
712
- robRefInput: { outputIndex: 0n, txHash: fromHex('') },
713
- },
714
- ],
715
- [
716
- mockUtxo(100n),
717
- {
718
- iasset: fromHex(fromText('iBTC')),
719
- orderType: {
720
- BuyIAssetOrder: {
721
- collateralAsset: adaAssetClass,
722
- maxPrice: { numerator: 1n, denominator: 1n },
723
- },
724
- },
725
- owner: fromHex(''),
726
- robRefInput: { outputIndex: 0n, txHash: fromHex('') },
727
- },
728
- ],
729
- [
730
- mockUtxo(100n, mkAssetsOf(collateralAssetA, 100n)),
731
- {
732
- iasset: fromHex(fromText('iUSD')),
733
- orderType: {
734
- BuyIAssetOrder: {
735
- collateralAsset: collateralAssetA,
736
- maxPrice: { numerator: 1n, denominator: 1n },
737
- },
738
- },
739
- owner: fromHex(''),
740
- robRefInput: { outputIndex: 0n, txHash: fromHex('') },
741
- },
742
- ],
743
- ];
744
-
745
- expect(() =>
746
- randomRobsSubsetSatisfyingTargetCollateral(
747
- fromHex(fromText('iUSD')),
748
- collateralAssetA,
749
- 110n,
750
- { numerator: 1n, denominator: 1n },
751
- lrps,
752
- MAX_REDEMPTIONS_WITH_CDP_OPEN,
753
- ),
754
- ).toThrow("Couldn't achieve target lovelaces");
755
- });
756
-
757
- test('filtering by price 1', () => {
758
- const lrps: [UTxO, RobDatum][] = [
759
- [
760
- mockUtxo(100n),
761
- {
762
- iasset: fromHex(fromText('iUSD')),
763
- orderType: {
764
- BuyIAssetOrder: {
765
- collateralAsset: collateralAssetA,
766
- maxPrice: { numerator: 15n, denominator: 10n },
767
- },
768
- },
769
- owner: fromHex(''),
770
- robRefInput: { outputIndex: 0n, txHash: fromHex('') },
771
- },
772
- ],
773
- [
774
- mockUtxo(100n),
775
- {
776
- iasset: fromHex(fromText('iUSD')),
777
- orderType: {
778
- BuyIAssetOrder: {
779
- collateralAsset: collateralAssetA,
780
- maxPrice: { numerator: 1n, denominator: 1n },
781
- },
782
- },
783
- owner: fromHex(''),
784
- robRefInput: { outputIndex: 0n, txHash: fromHex('') },
785
- },
786
- ],
787
- ];
788
-
789
- expect(() =>
790
- randomRobsSubsetSatisfyingTargetCollateral(
791
- fromHex(fromText('iUSD')),
792
- adaAssetClass,
793
- 120n,
794
- { numerator: 1n, denominator: 1n },
795
- lrps,
796
- MAX_REDEMPTIONS_WITH_CDP_OPEN,
797
- ),
798
- ).toThrow("Couldn't achieve target lovelaces");
799
- });
800
-
801
- test('filtering by price 2', () => {
802
- const lrps: [UTxO, RobDatum][] = [
803
- [
804
- mockUtxo(10n, mkAssetsOf(collateralAssetA, 100n)),
805
- {
806
- iasset: fromHex(fromText('iUSD')),
807
- orderType: {
808
- BuyIAssetOrder: {
809
- collateralAsset: collateralAssetA,
810
- maxPrice: { numerator: 15n, denominator: 10n },
811
- },
812
- },
813
- owner: fromHex(''),
814
- robRefInput: { outputIndex: 0n, txHash: fromHex('') },
815
- },
816
- ],
817
- [
818
- mockUtxo(10n, mkAssetsOf(collateralAssetA, 100n)),
819
- {
820
- iasset: fromHex(fromText('iUSD')),
821
- orderType: {
822
- BuyIAssetOrder: {
823
- collateralAsset: collateralAssetA,
824
- maxPrice: { numerator: 1n, denominator: 1n },
825
- },
826
- },
827
- owner: fromHex(''),
828
- robRefInput: { outputIndex: 0n, txHash: fromHex('') },
829
- },
830
- ],
831
- [
832
- mockUtxo(10n, mkAssetsOf(collateralAssetA, 100n)),
833
- {
834
- iasset: fromHex(fromText('iUSD')),
835
- orderType: {
836
- BuyIAssetOrder: {
837
- collateralAsset: collateralAssetA,
838
- maxPrice: { numerator: 13n, denominator: 10n },
839
- },
840
- },
841
- owner: fromHex(''),
842
- robRefInput: { outputIndex: 0n, txHash: fromHex('') },
843
- },
844
- ],
845
- ];
846
-
847
- expect(
848
- randomRobsSubsetSatisfyingTargetCollateral(
849
- fromHex(fromText('iUSD')),
850
- collateralAssetA,
851
- 120n,
852
- { numerator: 11n, denominator: 10n },
853
- lrps,
854
- MAX_REDEMPTIONS_WITH_CDP_OPEN,
855
- ),
856
- ).toEqual(expect.arrayContaining([lrps[0], lrps[2]]));
857
- });
858
-
859
- test('max redemptions check 1', () => {
860
- const lrps: [UTxO, RobDatum][] = [
861
- [
862
- mockUtxo(10n, mkAssetsOf(collateralAssetA, 100n)),
863
- {
864
- iasset: fromHex(fromText('iUSD')),
865
- orderType: {
866
- BuyIAssetOrder: {
867
- collateralAsset: collateralAssetA,
868
- maxPrice: { numerator: 13n, denominator: 10n },
869
- },
870
- },
871
- owner: fromHex(''),
872
- robRefInput: { outputIndex: 0n, txHash: fromHex('') },
873
- },
874
- ],
875
- [
876
- mockUtxo(10n, mkAssetsOf(collateralAssetA, 90n)),
877
- {
878
- iasset: fromHex(fromText('iUSD')),
879
- orderType: {
880
- BuyIAssetOrder: {
881
- collateralAsset: collateralAssetA,
882
- maxPrice: { numerator: 13n, denominator: 10n },
883
- },
884
- },
885
- owner: fromHex(''),
886
- robRefInput: { outputIndex: 0n, txHash: fromHex('') },
887
- },
888
- ],
889
- [
890
- mockUtxo(10n, mkAssetsOf(collateralAssetA, 80n)),
891
- {
892
- iasset: fromHex(fromText('iUSD')),
893
- orderType: {
894
- BuyIAssetOrder: {
895
- collateralAsset: collateralAssetA,
896
- maxPrice: { numerator: 13n, denominator: 10n },
897
- },
898
- },
899
- owner: fromHex(''),
900
- robRefInput: { outputIndex: 0n, txHash: fromHex('') },
901
- },
902
- ],
903
- [
904
- mockUtxo(10n, mkAssetsOf(collateralAssetA, 70n)),
905
- {
906
- iasset: fromHex(fromText('iUSD')),
907
- orderType: {
908
- BuyIAssetOrder: {
909
- collateralAsset: collateralAssetA,
910
- maxPrice: { numerator: 13n, denominator: 10n },
911
- },
912
- },
913
- owner: fromHex(''),
914
- robRefInput: { outputIndex: 0n, txHash: fromHex('') },
915
- },
916
- ],
917
- [
918
- mockUtxo(10n, mkAssetsOf(collateralAssetA, 100n)),
919
- {
920
- iasset: fromHex(fromText('iUSD')),
921
- orderType: {
922
- BuyIAssetOrder: {
923
- collateralAsset: collateralAssetA,
924
- maxPrice: { numerator: 13n, denominator: 10n },
925
- },
926
- },
927
- owner: fromHex(''),
928
- robRefInput: { outputIndex: 0n, txHash: fromHex('') },
929
- },
930
- ],
931
- ];
932
-
933
- const mockedShuffle = vi.fn().mockImplementation(() => lrps);
934
-
935
- expect(MAX_REDEMPTIONS_WITH_CDP_OPEN).toBe(4);
936
-
937
- // replaces the lrps[3] with lrps[4] since it's larger and already hitting max redemptions
938
- expect(
939
- randomRobsSubsetSatisfyingTargetCollateral(
940
- fromHex(fromText('iUSD')),
941
- collateralAssetA,
942
- 360n,
943
- { numerator: 1n, denominator: 1n },
944
- lrps,
945
- MAX_REDEMPTIONS_WITH_CDP_OPEN,
946
- mockedShuffle,
947
- ),
948
- ).toEqual(expect.arrayContaining([lrps[0], lrps[1], lrps[2], lrps[4]]));
949
- });
950
- });
951
-
952
- describe('robAmountToSpend', () => {
953
- const mockUtxo = (ada: bigint, otherAssets: Assets = {}): UTxO => ({
954
- address: '',
955
- assets: addAssets(mkLovelacesOf(ada), otherAssets),
956
- outputIndex: 0,
957
- txHash: '',
958
- });
959
-
960
- test('1', () => {
961
- expect(
962
- robCollateralAmtToSpend(
963
- mockUtxo(100n, mkAssetsOf(collateralAssetA, 30n)).assets,
964
- {
965
- BuyIAssetOrder: {
966
- collateralAsset: collateralAssetA,
967
- maxPrice: { numerator: 13n, denominator: 10n },
968
- },
969
- },
970
- ),
971
- ).toEqual<bigint>(30n);
972
- });
973
-
974
- test('2', () => {
975
- expect(
976
- robCollateralAmtToSpend(mockUtxo(20_000_000n).assets, {
977
- BuyIAssetOrder: {
978
- collateralAsset: adaAssetClass,
979
- maxPrice: { numerator: 13n, denominator: 10n },
980
- },
981
- }),
982
- ).toEqual<bigint>(20_000_000n - MIN_ROB_COLLATERAL_AMT);
983
- });
984
-
985
- test('Less than min rob collateral', () => {
986
- expect(
987
- robCollateralAmtToSpend(mockUtxo(2_000_000n).assets, {
988
- BuyIAssetOrder: {
989
- collateralAsset: adaAssetClass,
990
- maxPrice: { numerator: 13n, denominator: 10n },
991
- },
992
- }),
993
- ).toEqual<bigint>(0n);
994
- });
995
- });
996
-
997
- describe('calculateTotalCollateralForRedemption', () => {
998
- const mockUtxo = (ada: bigint, otherAssets: Assets = {}): UTxO => ({
999
- address: '',
1000
- assets: addAssets(mkLovelacesOf(ada), otherAssets),
1001
- outputIndex: 0,
1002
- txHash: '',
1003
- });
1004
-
1005
- test('1', () => {
1006
- const lrps: [UTxO, RobDatum][] = [
1007
- [
1008
- mockUtxo(100_000_000n),
1009
- {
1010
- iasset: fromHex(fromText('iUSD')),
1011
- orderType: {
1012
- BuyIAssetOrder: {
1013
- collateralAsset: adaAssetClass,
1014
- maxPrice: { numerator: 13n, denominator: 10n },
1015
- },
1016
- },
1017
- owner: fromHex(''),
1018
- robRefInput: { outputIndex: 0n, txHash: fromHex('') },
1019
- },
1020
- ],
1021
- [
1022
- mockUtxo(100_000_000n),
1023
- {
1024
- iasset: fromHex(fromText('iUSD')),
1025
- orderType: {
1026
- BuyIAssetOrder: {
1027
- collateralAsset: adaAssetClass,
1028
- maxPrice: { numerator: 13n, denominator: 10n },
1029
- },
1030
- },
1031
- owner: fromHex(''),
1032
- robRefInput: { outputIndex: 0n, txHash: fromHex('') },
1033
- },
1034
- ],
1035
- ];
1036
-
1037
- expect(
1038
- calculateTotalCollateralForRedemption(
1039
- fromHex(fromText('iUSD')),
1040
- adaAssetClass,
1041
- { numerator: 1n, denominator: 1n },
1042
- lrps,
1043
- MAX_REDEMPTIONS_WITH_CDP_OPEN,
1044
- ),
1045
- ).toEqual<bigint>(200_000_000n - MIN_ROB_COLLATERAL_AMT * 2n);
1046
- });
1047
-
1048
- test('2', () => {
1049
- const lrps: [UTxO, RobDatum][] = [
1050
- [
1051
- mockUtxo(100_000_000n),
1052
- {
1053
- iasset: fromHex(fromText('iUSD')),
1054
- orderType: {
1055
- BuyIAssetOrder: {
1056
- collateralAsset: adaAssetClass,
1057
- maxPrice: { numerator: 13n, denominator: 10n },
1058
- },
1059
- },
1060
- owner: fromHex(''),
1061
- robRefInput: { outputIndex: 0n, txHash: fromHex('') },
1062
- },
1063
- ],
1064
- [
1065
- mockUtxo(1000n),
1066
- {
1067
- iasset: fromHex(fromText('iUSD')),
1068
- orderType: {
1069
- BuyIAssetOrder: {
1070
- collateralAsset: collateralAssetA,
1071
- maxPrice: { numerator: 13n, denominator: 10n },
1072
- },
1073
- },
1074
- owner: fromHex(''),
1075
- robRefInput: { outputIndex: 0n, txHash: fromHex('') },
1076
- },
1077
- ],
1078
- ];
1079
-
1080
- expect(
1081
- calculateTotalCollateralForRedemption(
1082
- fromHex(fromText('iUSD')),
1083
- adaAssetClass,
1084
- { numerator: 1n, denominator: 1n },
1085
- lrps,
1086
- MAX_REDEMPTIONS_WITH_CDP_OPEN,
1087
- ),
1088
- ).toEqual<bigint>(100_000_000n - MIN_ROB_COLLATERAL_AMT);
1089
- });
1090
-
1091
- test('filtering by assets 1', () => {
1092
- const lrps: [UTxO, RobDatum][] = [
1093
- [
1094
- mockUtxo(100_000_000n),
1095
- {
1096
- iasset: fromHex(fromText('iUSD')),
1097
- orderType: {
1098
- BuyIAssetOrder: {
1099
- collateralAsset: adaAssetClass,
1100
- maxPrice: { numerator: 13n, denominator: 10n },
1101
- },
1102
- },
1103
- owner: fromHex(''),
1104
- robRefInput: { outputIndex: 0n, txHash: fromHex('') },
1105
- },
1106
- ],
1107
- [
1108
- mockUtxo(100_000_000n),
1109
- {
1110
- iasset: fromHex(fromText('iBTC')),
1111
- orderType: {
1112
- BuyIAssetOrder: {
1113
- collateralAsset: adaAssetClass,
1114
- maxPrice: { numerator: 13n, denominator: 10n },
1115
- },
1116
- },
1117
- owner: fromHex(''),
1118
- robRefInput: { outputIndex: 0n, txHash: fromHex('') },
1119
- },
1120
- ],
1121
- [
1122
- mockUtxo(100_000_000n),
1123
- {
1124
- iasset: fromHex(fromText('iETH')),
1125
- orderType: {
1126
- BuyIAssetOrder: {
1127
- collateralAsset: adaAssetClass,
1128
- maxPrice: { numerator: 13n, denominator: 10n },
1129
- },
1130
- },
1131
- owner: fromHex(''),
1132
- robRefInput: { outputIndex: 0n, txHash: fromHex('') },
1133
- },
1134
- ],
1135
- ];
1136
-
1137
- expect(
1138
- calculateTotalCollateralForRedemption(
1139
- fromHex(fromText('iUSD')),
1140
- adaAssetClass,
1141
- { numerator: 1n, denominator: 1n },
1142
- lrps,
1143
- MAX_REDEMPTIONS_WITH_CDP_OPEN,
1144
- ),
1145
- ).toEqual<bigint>(100_000_000n - MIN_ROB_COLLATERAL_AMT);
1146
- });
1147
-
1148
- test('filtering by price 1', () => {
1149
- const lrps: [UTxO, RobDatum][] = [
1150
- [
1151
- mockUtxo(1000_000_000n),
1152
- {
1153
- iasset: fromHex(fromText('iUSD')),
1154
- orderType: {
1155
- BuyIAssetOrder: {
1156
- collateralAsset: adaAssetClass,
1157
- maxPrice: { numerator: 1n, denominator: 1n },
1158
- },
1159
- },
1160
- owner: fromHex(''),
1161
- robRefInput: { outputIndex: 0n, txHash: fromHex('') },
1162
- },
1163
- ],
1164
- [
1165
- mockUtxo(1000_000_000n),
1166
- {
1167
- iasset: fromHex(fromText('iUSD')),
1168
- orderType: {
1169
- BuyIAssetOrder: {
1170
- collateralAsset: adaAssetClass,
1171
- maxPrice: { numerator: 15n, denominator: 10n },
1172
- },
1173
- },
1174
- owner: fromHex(''),
1175
- robRefInput: { outputIndex: 0n, txHash: fromHex('') },
1176
- },
1177
- ],
1178
- [
1179
- mockUtxo(1000_000_000n),
1180
- {
1181
- iasset: fromHex(fromText('iUSD')),
1182
- orderType: {
1183
- BuyIAssetOrder: {
1184
- collateralAsset: adaAssetClass,
1185
- maxPrice: { numerator: 8n, denominator: 10n },
1186
- },
1187
- },
1188
- owner: fromHex(''),
1189
- robRefInput: { outputIndex: 0n, txHash: fromHex('') },
1190
- },
1191
- ],
1192
- ];
1193
-
1194
- expect(
1195
- calculateTotalCollateralForRedemption(
1196
- fromHex(fromText('iUSD')),
1197
- adaAssetClass,
1198
- { numerator: 11n, denominator: 10n },
1199
- lrps,
1200
- MAX_REDEMPTIONS_WITH_CDP_OPEN,
1201
- ),
1202
- ).toEqual<bigint>(1000_000_000n - MIN_ROB_COLLATERAL_AMT);
1203
- });
1204
-
1205
- test('capping by max redemptions 1', () => {
1206
- const lrps: [UTxO, RobDatum][] = [
1207
- [
1208
- mockUtxo(100_000_000n),
1209
- {
1210
- iasset: fromHex(fromText('iUSD')),
1211
- orderType: {
1212
- BuyIAssetOrder: {
1213
- collateralAsset: adaAssetClass,
1214
- maxPrice: { numerator: 1n, denominator: 1n },
1215
- },
1216
- },
1217
- owner: fromHex(''),
1218
- robRefInput: { outputIndex: 0n, txHash: fromHex('') },
1219
- },
1220
- ],
1221
- [
1222
- mockUtxo(140_000_000n),
1223
- {
1224
- iasset: fromHex(fromText('iUSD')),
1225
- orderType: {
1226
- BuyIAssetOrder: {
1227
- collateralAsset: adaAssetClass,
1228
- maxPrice: { numerator: 1n, denominator: 1n },
1229
- },
1230
- },
1231
- owner: fromHex(''),
1232
- robRefInput: { outputIndex: 0n, txHash: fromHex('') },
1233
- },
1234
- ],
1235
- [
1236
- mockUtxo(160_000_000n),
1237
- {
1238
- iasset: fromHex(fromText('iUSD')),
1239
- orderType: {
1240
- BuyIAssetOrder: {
1241
- collateralAsset: adaAssetClass,
1242
- maxPrice: { numerator: 1n, denominator: 1n },
1243
- },
1244
- },
1245
- owner: fromHex(''),
1246
- robRefInput: { outputIndex: 0n, txHash: fromHex('') },
1247
- },
1248
- ],
1249
- [
1250
- mockUtxo(180_000_000n),
1251
- {
1252
- iasset: fromHex(fromText('iUSD')),
1253
- orderType: {
1254
- BuyIAssetOrder: {
1255
- collateralAsset: adaAssetClass,
1256
- maxPrice: { numerator: 1n, denominator: 1n },
1257
- },
1258
- },
1259
- owner: fromHex(''),
1260
- robRefInput: { outputIndex: 0n, txHash: fromHex('') },
1261
- },
1262
- ],
1263
- [
1264
- mockUtxo(200_000_000n),
1265
- {
1266
- iasset: fromHex(fromText('iUSD')),
1267
- orderType: {
1268
- BuyIAssetOrder: {
1269
- collateralAsset: adaAssetClass,
1270
- maxPrice: { numerator: 1n, denominator: 1n },
1271
- },
1272
- },
1273
- owner: fromHex(''),
1274
- robRefInput: { outputIndex: 0n, txHash: fromHex('') },
1275
- },
1276
- ],
1277
- ];
1278
-
1279
- expect(MAX_REDEMPTIONS_WITH_CDP_OPEN).toBe(4);
1280
-
1281
- expect(
1282
- calculateTotalCollateralForRedemption(
1283
- fromHex(fromText('iUSD')),
1284
- adaAssetClass,
1285
- { numerator: 1n, denominator: 1n },
1286
- lrps,
1287
- MAX_REDEMPTIONS_WITH_CDP_OPEN,
1288
- ),
1289
- // I.e. the one with 1000n lovelaces is dropped
1290
- ).toEqual<bigint>(680_000_000n - MIN_ROB_COLLATERAL_AMT * 4n);
1291
- });
1292
- });
1293
-
1294
- describe('LRP leverage', () => {
1295
- beforeEach<MyContext>(async (context: MyContext) => {
1296
- context.users = {
1297
- admin: generateEmulatorAccount(
1298
- addAssets(
1299
- mkLovelacesOf(100_000_000_000_000n),
1300
- mkAssetsOf(collateralAssetA, 100_000_000_000n),
1301
- ),
1302
- ),
1303
- user: generateEmulatorAccount(addAssets(mkLovelacesOf(150_000_000n))),
1304
- };
1305
-
1306
- context.emulator = new Emulator(
1307
- [context.users.admin, context.users.user],
1308
- MAINNET_PROTOCOL_PARAMETERS,
1309
- );
1310
- context.lucid = await Lucid(context.emulator, 'Custom');
1311
- });
1312
-
1313
- test<MyContext>('Open 2x leveraged CDP; 1 LRP; price ~1.1; f_r=.01; f_m=.005', async (context: MyContext) => {
1314
- context.lucid.selectWallet.fromSeed(context.users.admin.seedPhrase);
1315
-
1316
- const [sysParams, [iusdAssetInfo]] = await init(context.lucid, [
1317
- {
1318
- ...iusdInitialAssetCfg(),
1319
- collateralAssets: [
1320
- {
1321
- ...mkBaseCollateralAsset(adaAssetClass, 0n, {
1322
- numerator: 1_104_093n,
1323
- denominator: 1_000_000n,
1324
- }),
1325
- maintenanceRatio: { numerator: 15n, denominator: 10n },
1326
- },
1327
- ],
1328
- debtMintingFeeRatio: { numerator: 1n, denominator: 200n },
1329
- redemptionReimbursementRatio: { numerator: 1n, denominator: 100n },
1330
- },
1331
- ]);
1332
-
1333
- await openBuyRobs(
1334
- context,
1335
- sysParams,
1336
- iusdAssetInfo.iassetTokenNameAscii,
1337
- adaAssetClass,
1338
- [100_000_000n],
1339
- { numerator: 15n, denominator: 10n },
1340
- );
1341
-
1342
- const allRobs = await findAllRobs(
1343
- context.lucid,
1344
- sysParams,
1345
- iusdAssetInfo.iassetTokenNameAscii,
1346
- );
1347
-
1348
- const orefs = await findAllNecessaryOrefs(
1349
- context.lucid,
1350
- sysParams,
1351
- iusdAssetInfo.iassetTokenNameAscii,
1352
- adaAssetClass,
1353
- );
1354
-
1355
- const priceOracleUtxo = await findPriceOracleFromCollateralAsset(
1356
- context.lucid,
1357
- orefs.collateralAsset,
1358
- );
1359
-
1360
- if (priceOracleUtxo == null) {
1361
- throw new Error('Expected oracle UTXO');
1362
- }
1363
-
1364
- const baseCollateral = 20_000_000n;
1365
-
1366
- await benchmarkAndAwaitTx(
1367
- 'Leverage - CDP open with 1 LRP',
1368
- await leverageCdpWithRob(
1369
- 2,
1370
- baseCollateral,
1371
- priceOracleUtxo,
1372
- orefs.iasset.utxo,
1373
- orefs.collateralAsset.utxo,
1374
- orefs.cdpCreatorUtxo,
1375
- orefs.interestOracleUtxo,
1376
- orefs.treasuryUtxo,
1377
- sysParams,
1378
- context.lucid,
1379
- allRobs.map((lrps) => [lrps.utxo, lrps.datum]),
1380
- ),
1381
- context.lucid,
1382
- context.emulator,
1383
- );
1384
-
1385
- const [pkh, skh] = await addrDetails(context.lucid);
1386
-
1387
- const res = await findCdp(
1388
- context.lucid,
1389
- sysParams.validatorHashes.cdpHash,
1390
- fromSystemParamsAsset(sysParams.cdpParams.cdpAuthToken),
1391
- pkh.hash,
1392
- skh,
1393
- );
1394
-
1395
- // Assert leverage
1396
- assertValueInRange(
1397
- Number(lovelacesAmt(res.utxo.assets)) / Number(baseCollateral),
1398
- {
1399
- min: 1.999,
1400
- max: 2.0,
1401
- },
1402
- );
1403
-
1404
- // Assert collateral ratio
1405
- assertValueInRange(
1406
- cdpCollateralRatioPercentage(
1407
- BigInt(context.lucid.slotToUnixTime(context.lucid.currentSlot())),
1408
- parsePriceOracleDatum(getInlineDatumOrThrow(priceOracleUtxo)).price,
1409
- res.utxo.assets,
1410
- res.datum,
1411
- parseInterestOracleDatum(
1412
- getInlineDatumOrThrow(orefs.interestOracleUtxo),
1413
- ),
1414
- ),
1415
- {
1416
- min: 197,
1417
- max: 197.001,
1418
- },
1419
- );
1420
- });
1421
-
1422
- test<MyContext>('Pyth oracle - Open 2x leveraged CDP; 1 LRP; price ~1.1; f_r=.01; f_m=.005', async (context: MyContext) => {
1423
- context.lucid.selectWallet.fromSeed(context.users.admin.seedPhrase);
1424
-
1425
- const [sysParams, [iusdAssetInfo]] = await init(
1426
- context.lucid,
1427
- [],
1428
-
1429
- (pythStateNft: AssetClass) => [
1430
- iusdInitialAssetCfgWithPyth(pythStateNft, (pythStatePolicyId) => [
1431
- mkBaseCollateralAsset(
1432
- adaAssetClass,
1433
- 0n,
1434
- DEFAULT_PRICE,
1435
- 0n,
1436
- pythStatePolicyId,
1437
- {
1438
- tag: 'value',
1439
- val: { priceFeedId: 1 },
1440
- },
1441
- ),
1442
- ]),
1443
- ],
1444
- );
1445
-
1446
- await openBuyRobs(
1447
- context,
1448
- sysParams,
1449
- iusdAssetInfo.iassetTokenNameAscii,
1450
- adaAssetClass,
1451
- [100_000_000n],
1452
- { numerator: 15n, denominator: 10n },
1453
- );
1454
-
1455
- const allRobs = await findAllRobs(
1456
- context.lucid,
1457
- sysParams,
1458
- iusdAssetInfo.iassetTokenNameAscii,
1459
- );
1460
-
1461
- const orefs = await findAllNecessaryOrefs(
1462
- context.lucid,
1463
- sysParams,
1464
- iusdAssetInfo.iassetTokenNameAscii,
1465
- adaAssetClass,
1466
- );
1467
-
1468
- const priceOracleUtxo = await findPriceOracleFromCollateralAsset(
1469
- context.lucid,
1470
- orefs.collateralAsset,
1471
- );
1472
-
1473
- const currentTime = BigInt(
1474
- context.lucid.slotToUnixTime(context.lucid.currentSlot()),
1475
- );
1476
-
1477
- const iUsdFeed: ParsedFeedPayload = {
1478
- priceFeedId: 1,
1479
- price: '1104093',
1480
- exponent: -6,
1481
- };
1482
- const message = toHex(
1483
- await createPythMessage([iUsdFeed], currentTime * 1_000n),
1484
- );
1485
-
1486
- const pythStateOref = await context.lucid.utxoByUnit(
1487
- assetClassToUnit(
1488
- fromSystemParamsAsset(sysParams.pythConfig.pythStateAssetClass),
1489
- ),
1490
- );
1491
-
1492
- const [price, _] = await retrieveAdjustedPrice(
1493
- orefs.iasset.datum.assetName,
1494
- orefs.collateralAsset.datum.collateralAsset,
1495
- orefs.collateralAsset.datum.priceInfo,
1496
- orefs.collateralAsset.datum.extraDecimals,
1497
- priceOracleUtxo,
1498
- message,
1499
- sysParams.pythConfig,
1500
- context.lucid,
1501
- );
1502
-
1503
- const baseCollateral = 20_000_000n;
1504
-
1505
- await benchmarkAndAwaitTx(
1506
- 'Leverage - CDP open with 1 LRP using Pyth oracle',
1507
- await leverageCdpWithRob(
1508
- 2,
1509
- baseCollateral,
1510
- priceOracleUtxo,
1511
- orefs.iasset.utxo,
1512
- orefs.collateralAsset.utxo,
1513
- orefs.cdpCreatorUtxo,
1514
- orefs.interestOracleUtxo,
1515
- orefs.treasuryUtxo,
1516
- sysParams,
1517
- context.lucid,
1518
- allRobs.map((lrps) => [lrps.utxo, lrps.datum]),
1519
-
1520
- message,
1521
- pythStateOref,
1522
- ),
1523
- context.lucid,
1524
- context.emulator,
1525
- );
1526
-
1527
- const [pkh, skh] = await addrDetails(context.lucid);
1528
-
1529
- const res = await findCdp(
1530
- context.lucid,
1531
- sysParams.validatorHashes.cdpHash,
1532
- fromSystemParamsAsset(sysParams.cdpParams.cdpAuthToken),
1533
- pkh.hash,
1534
- skh,
1535
- );
1536
-
1537
- // Assert leverage
1538
- assertValueInRange(
1539
- Number(lovelacesAmt(res.utxo.assets)) / Number(baseCollateral),
1540
- {
1541
- min: 1.999,
1542
- max: 2.0,
1543
- },
1544
- );
1545
-
1546
- // Assert collateral ratio
1547
- assertValueInRange(
1548
- cdpCollateralRatioPercentage(
1549
- BigInt(context.lucid.slotToUnixTime(context.lucid.currentSlot())),
1550
- price,
1551
- res.utxo.assets,
1552
- res.datum,
1553
- parseInterestOracleDatum(
1554
- getInlineDatumOrThrow(orefs.interestOracleUtxo),
1555
- ),
1556
- ),
1557
- {
1558
- min: 197,
1559
- max: 197.001,
1560
- },
1561
- );
1562
- });
1563
-
1564
- test<MyContext>('Open 2x leveraged CDP; 4 LRPs; price ~0.9; f_r=.01; f_m=.005', async (context: MyContext) => {
1565
- context.lucid.selectWallet.fromSeed(context.users.admin.seedPhrase);
1566
-
1567
- const [sysParams, [iusdAssetInfo]] = await init(context.lucid, [
1568
- {
1569
- ...iusdInitialAssetCfg(),
1570
- collateralAssets: [
1571
- {
1572
- ...mkBaseCollateralAsset(adaAssetClass, 0n, {
1573
- numerator: 904_093n,
1574
- denominator: 1_000_000n,
1575
- }),
1576
- maintenanceRatio: { numerator: 15n, denominator: 10n },
1577
- },
1578
- ],
1579
- debtMintingFeeRatio: { numerator: 1n, denominator: 200n },
1580
- redemptionReimbursementRatio: { numerator: 1n, denominator: 100n },
1581
- },
1582
- ]);
1583
-
1584
- await openBuyRobs(
1585
- context,
1586
- sysParams,
1587
- iusdAssetInfo.iassetTokenNameAscii,
1588
- adaAssetClass,
1589
- [26_250_000n, 26_250_000n, 26_250_000n, 26_250_000n],
1590
- { numerator: 15n, denominator: 10n },
1591
- );
1592
-
1593
- const allRobs = await findAllRobs(
1594
- context.lucid,
1595
- sysParams,
1596
- iusdAssetInfo.iassetTokenNameAscii,
1597
- );
1598
-
1599
- const orefs = await findAllNecessaryOrefs(
1600
- context.lucid,
1601
- sysParams,
1602
- iusdAssetInfo.iassetTokenNameAscii,
1603
- adaAssetClass,
1604
- );
1605
-
1606
- const priceOracleUtxo = await findPriceOracleFromCollateralAsset(
1607
- context.lucid,
1608
- orefs.collateralAsset,
1609
- );
1610
-
1611
- if (priceOracleUtxo == null) {
1612
- throw new Error('Expected oracle UTXO');
1613
- }
1614
-
1615
- const baseCollateral = 100_000_000n;
1616
- await runAndAwaitTx(
1617
- context.lucid,
1618
- leverageCdpWithRob(
1619
- 2,
1620
- baseCollateral,
1621
- priceOracleUtxo,
1622
- orefs.iasset.utxo,
1623
- orefs.collateralAsset.utxo,
1624
- orefs.cdpCreatorUtxo,
1625
- orefs.interestOracleUtxo,
1626
- orefs.treasuryUtxo,
1627
- sysParams,
1628
- context.lucid,
1629
- allRobs.map((lrps) => [lrps.utxo, lrps.datum]),
1630
- ),
1631
- );
1632
-
1633
- const [pkh, skh] = await addrDetails(context.lucid);
1634
-
1635
- const res = await findCdp(
1636
- context.lucid,
1637
- sysParams.validatorHashes.cdpHash,
1638
- fromSystemParamsAsset(sysParams.cdpParams.cdpAuthToken),
1639
- pkh.hash,
1640
- skh,
1641
- );
1642
-
1643
- // Assert leverage
1644
- assertValueInRange(
1645
- Number(lovelacesAmt(res.utxo.assets)) / Number(baseCollateral),
1646
- {
1647
- min: 1.999,
1648
- max: 2.0,
1649
- },
1650
- );
1651
-
1652
- // Assert collateral ratio
1653
- assertValueInRange(
1654
- cdpCollateralRatioPercentage(
1655
- BigInt(context.lucid.slotToUnixTime(context.lucid.currentSlot())),
1656
- parsePriceOracleDatum(getInlineDatumOrThrow(priceOracleUtxo)).price,
1657
- res.utxo.assets,
1658
- res.datum,
1659
- parseInterestOracleDatum(
1660
- getInlineDatumOrThrow(orefs.interestOracleUtxo),
1661
- ),
1662
- ),
1663
- {
1664
- min: 197,
1665
- max: 197.001,
1666
- },
1667
- );
1668
-
1669
- {
1670
- const lrps = await findAllRobs(
1671
- context.lucid,
1672
- sysParams,
1673
- iusdAssetInfo.iassetTokenNameAscii,
1674
- );
1675
- expect(
1676
- lrps.every((lrp) => hadRobRedemption(lrp, sysParams)),
1677
- ).toBeTruthy();
1678
- }
1679
- });
1680
-
1681
- test<MyContext>('Open 2.3x leveraged CDP; 4 LRPs; price ~1.03; f_r=.01; f_m=.013', async (context: MyContext) => {
1682
- context.lucid.selectWallet.fromSeed(context.users.admin.seedPhrase);
1683
-
1684
- const [sysParams, [iusdAssetInfo]] = await init(context.lucid, [
1685
- {
1686
- ...iusdInitialAssetCfg(),
1687
- collateralAssets: [
1688
- {
1689
- ...mkBaseCollateralAsset(adaAssetClass, 0n, {
1690
- numerator: 1_037_093n,
1691
- denominator: 1_000_000n,
1692
- }),
1693
- maintenanceRatio: { numerator: 15n, denominator: 10n },
1694
- },
1695
- ],
1696
- debtMintingFeeRatio: { numerator: 13n, denominator: 1_000n },
1697
- redemptionReimbursementRatio: { numerator: 1n, denominator: 100n },
1698
- },
1699
- ]);
1700
-
1701
- await openBuyRobs(
1702
- context,
1703
- sysParams,
1704
- iusdAssetInfo.iassetTokenNameAscii,
1705
- adaAssetClass,
1706
- [35_139_729n, 35_000_397n, 35_001_079n, 35_107_049n],
1707
- { numerator: 15n, denominator: 10n },
1708
- );
1709
-
1710
- const allLrps = await findAllRobs(
1711
- context.lucid,
1712
- sysParams,
1713
- iusdAssetInfo.iassetTokenNameAscii,
1714
- );
1715
-
1716
- const orefs = await findAllNecessaryOrefs(
1717
- context.lucid,
1718
- sysParams,
1719
- iusdAssetInfo.iassetTokenNameAscii,
1720
- adaAssetClass,
1721
- );
1722
-
1723
- const priceOracleUtxo = await findPriceOracleFromCollateralAsset(
1724
- context.lucid,
1725
- orefs.collateralAsset,
1726
- );
1727
-
1728
- if (priceOracleUtxo == null) {
1729
- throw new Error('Expected oracle UTXO');
1730
- }
1731
-
1732
- const baseCollateral = 100_000_000n;
1733
- await runAndAwaitTx(
1734
- context.lucid,
1735
- leverageCdpWithRob(
1736
- 2.3,
1737
- baseCollateral,
1738
- priceOracleUtxo,
1739
- orefs.iasset.utxo,
1740
- orefs.collateralAsset.utxo,
1741
- orefs.cdpCreatorUtxo,
1742
- orefs.interestOracleUtxo,
1743
- orefs.treasuryUtxo,
1744
- sysParams,
1745
- context.lucid,
1746
- allLrps.map((lrps) => [lrps.utxo, lrps.datum]),
1747
- ),
1748
- );
1749
-
1750
- const [pkh, skh] = await addrDetails(context.lucid);
1751
-
1752
- const res = await findCdp(
1753
- context.lucid,
1754
- sysParams.validatorHashes.cdpHash,
1755
- fromSystemParamsAsset(sysParams.cdpParams.cdpAuthToken),
1756
- pkh.hash,
1757
- skh,
1758
- );
1759
-
1760
- // Assert leverage
1761
- assertValueInRange(
1762
- Number(lovelacesAmt(res.utxo.assets)) / Number(baseCollateral),
1763
- {
1764
- min: 2.29999,
1765
- max: 2.3,
1766
- },
1767
- );
1768
-
1769
- // Assert collateral ratio
1770
- assertValueInRange(
1771
- cdpCollateralRatioPercentage(
1772
- BigInt(context.lucid.slotToUnixTime(context.lucid.currentSlot())),
1773
- parsePriceOracleDatum(getInlineDatumOrThrow(priceOracleUtxo)).price,
1774
- res.utxo.assets,
1775
- res.datum,
1776
- parseInterestOracleDatum(
1777
- getInlineDatumOrThrow(orefs.interestOracleUtxo),
1778
- ),
1779
- ),
1780
- {
1781
- min: 172,
1782
- max: 172.1,
1783
- },
1784
- );
1785
-
1786
- {
1787
- const lrps = await findAllRobs(
1788
- context.lucid,
1789
- sysParams,
1790
- iusdAssetInfo.iassetTokenNameAscii,
1791
- );
1792
- expect(
1793
- lrps.every((lrp) => hadRobRedemption(lrp, sysParams)),
1794
- ).toBeTruthy();
1795
- }
1796
- });
1797
-
1798
- test<MyContext>('Open 1.2x leveraged CDP 3 LRPs price ~1.46; f_r=.02; f_m=.007', async (context: MyContext) => {
1799
- context.lucid.selectWallet.fromSeed(context.users.admin.seedPhrase);
1800
-
1801
- const [sysParams, [iusdAssetInfo]] = await init(context.lucid, [
1802
- {
1803
- ...iusdInitialAssetCfg(),
1804
- collateralAssets: [
1805
- {
1806
- ...mkBaseCollateralAsset(adaAssetClass, 0n, {
1807
- numerator: 1_461_093n,
1808
- denominator: 1_000_000n,
1809
- }),
1810
- maintenanceRatio: { numerator: 15n, denominator: 10n },
1811
- },
1812
- ],
1813
- debtMintingFeeRatio: { numerator: 7n, denominator: 1_000n },
1814
- redemptionReimbursementRatio: { numerator: 2n, denominator: 100n },
1815
- },
1816
- ]);
1817
-
1818
- await openBuyRobs(
1819
- context,
1820
- sysParams,
1821
- iusdAssetInfo.iassetTokenNameAscii,
1822
- adaAssetClass,
1823
- [75_000_000n, 75_000_000n, 75_000_000n],
1824
- { numerator: 15n, denominator: 10n },
1825
- );
1826
-
1827
- const allLrps = await findAllRobs(
1828
- context.lucid,
1829
- sysParams,
1830
- iusdAssetInfo.iassetTokenNameAscii,
1831
- );
1832
-
1833
- const orefs = await findAllNecessaryOrefs(
1834
- context.lucid,
1835
- sysParams,
1836
- iusdAssetInfo.iassetTokenNameAscii,
1837
- adaAssetClass,
1838
- );
1839
-
1840
- const priceOracleUtxo = await findPriceOracleFromCollateralAsset(
1841
- context.lucid,
1842
- orefs.collateralAsset,
1843
- );
1844
-
1845
- if (priceOracleUtxo == null) {
1846
- throw new Error('Expected oracle UTXO');
1847
- }
1848
-
1849
- const baseCollateral = 1_000_000_000n;
1850
- await runAndAwaitTx(
1851
- context.lucid,
1852
- leverageCdpWithRob(
1853
- 1.2,
1854
- baseCollateral,
1855
- priceOracleUtxo,
1856
- orefs.iasset.utxo,
1857
- orefs.collateralAsset.utxo,
1858
- orefs.cdpCreatorUtxo,
1859
- orefs.interestOracleUtxo,
1860
- orefs.treasuryUtxo,
1861
- sysParams,
1862
- context.lucid,
1863
- allLrps.map((lrps) => [lrps.utxo, lrps.datum]),
1864
- ),
1865
- );
1866
-
1867
- const [pkh, skh] = await addrDetails(context.lucid);
1868
-
1869
- const res = await findCdp(
1870
- context.lucid,
1871
- sysParams.validatorHashes.cdpHash,
1872
- fromSystemParamsAsset(sysParams.cdpParams.cdpAuthToken),
1873
- pkh.hash,
1874
- skh,
1875
- );
1876
-
1877
- // Assert leverage
1878
- assertValueInRange(
1879
- Number(lovelacesAmt(res.utxo.assets)) / Number(baseCollateral),
1880
- {
1881
- min: 1.19999,
1882
- max: 1.2,
1883
- },
1884
- );
1885
-
1886
- // Assert collateral ratio
1887
- assertValueInRange(
1888
- cdpCollateralRatioPercentage(
1889
- BigInt(context.lucid.slotToUnixTime(context.lucid.currentSlot())),
1890
- parsePriceOracleDatum(getInlineDatumOrThrow(priceOracleUtxo)).price,
1891
- res.utxo.assets,
1892
- res.datum,
1893
- parseInterestOracleDatum(
1894
- getInlineDatumOrThrow(orefs.interestOracleUtxo),
1895
- ),
1896
- ),
1897
- {
1898
- min: 583,
1899
- max: 583.1,
1900
- },
1901
- );
1902
-
1903
- {
1904
- const lrps = await findAllRobs(
1905
- context.lucid,
1906
- sysParams,
1907
- iusdAssetInfo.iassetTokenNameAscii,
1908
- );
1909
- expect(
1910
- lrps.every((lrp) => hadRobRedemption(lrp, sysParams)),
1911
- ).toBeTruthy();
1912
- }
1913
- });
1914
-
1915
- test<MyContext>('Open 2.1x leveraged CDP 3 LRPs price ~0.0589; f_r=.02; f_m=.007', async (context: MyContext) => {
1916
- context.lucid.selectWallet.fromSeed(context.users.admin.seedPhrase);
1917
-
1918
- const [sysParams, [iusdAssetInfo]] = await init(context.lucid, [
1919
- {
1920
- ...iusdInitialAssetCfg(),
1921
- collateralAssets: [
1922
- {
1923
- ...mkBaseCollateralAsset(adaAssetClass, 0n, {
1924
- numerator: 58_900n,
1925
- denominator: 1_000_000n,
1926
- }),
1927
- maintenanceRatio: { numerator: 15n, denominator: 10n },
1928
- },
1929
- ],
1930
- debtMintingFeeRatio: { numerator: 7n, denominator: 1_000n },
1931
- redemptionReimbursementRatio: { numerator: 2n, denominator: 100n },
1932
- },
1933
- ]);
1934
-
1935
- await openBuyRobs(
1936
- context,
1937
- sysParams,
1938
- iusdAssetInfo.iassetTokenNameAscii,
1939
- adaAssetClass,
1940
- [400_000_000n, 400_000_000n, 400_000_000n],
1941
- { numerator: 15n, denominator: 10n },
1942
- );
1943
-
1944
- const allLrps = await findAllRobs(
1945
- context.lucid,
1946
- sysParams,
1947
- iusdAssetInfo.iassetTokenNameAscii,
1948
- );
1949
-
1950
- const orefs = await findAllNecessaryOrefs(
1951
- context.lucid,
1952
- sysParams,
1953
- iusdAssetInfo.iassetTokenNameAscii,
1954
- adaAssetClass,
1955
- );
1956
-
1957
- const priceOracleUtxo = await findPriceOracleFromCollateralAsset(
1958
- context.lucid,
1959
- orefs.collateralAsset,
1960
- );
1961
-
1962
- if (priceOracleUtxo == null) {
1963
- throw new Error('Expected oracle UTXO');
1964
- }
1965
-
1966
- const baseCollateral = 1_000_000_000n;
1967
- await runAndAwaitTx(
1968
- context.lucid,
1969
- leverageCdpWithRob(
1970
- 2.1,
1971
- baseCollateral,
1972
- priceOracleUtxo,
1973
- orefs.iasset.utxo,
1974
- orefs.collateralAsset.utxo,
1975
- orefs.cdpCreatorUtxo,
1976
- orefs.interestOracleUtxo,
1977
- orefs.treasuryUtxo,
1978
- sysParams,
1979
- context.lucid,
1980
- allLrps.map((lrps) => [lrps.utxo, lrps.datum]),
1981
- ),
1982
- );
1983
-
1984
- const [pkh, skh] = await addrDetails(context.lucid);
1985
-
1986
- const res = await findCdp(
1987
- context.lucid,
1988
- sysParams.validatorHashes.cdpHash,
1989
- fromSystemParamsAsset(sysParams.cdpParams.cdpAuthToken),
1990
- pkh.hash,
1991
- skh,
1992
- );
1993
-
1994
- // Assert leverage
1995
- assertValueInRange(
1996
- Number(lovelacesAmt(res.utxo.assets)) / Number(baseCollateral),
1997
- {
1998
- min: 2.099999,
1999
- max: 2.1,
2000
- },
2001
- );
2002
-
2003
- // Assert collateral ratio
2004
- assertValueInRange(
2005
- cdpCollateralRatioPercentage(
2006
- BigInt(context.lucid.slotToUnixTime(context.lucid.currentSlot())),
2007
- parsePriceOracleDatum(getInlineDatumOrThrow(priceOracleUtxo)).price,
2008
- res.utxo.assets,
2009
- res.datum,
2010
- parseInterestOracleDatum(
2011
- getInlineDatumOrThrow(orefs.interestOracleUtxo),
2012
- ),
2013
- ),
2014
- {
2015
- min: 185,
2016
- max: 185.1,
2017
- },
2018
- );
2019
-
2020
- {
2021
- const lrps = await findAllRobs(
2022
- context.lucid,
2023
- sysParams,
2024
- iusdAssetInfo.iassetTokenNameAscii,
2025
- );
2026
- expect(
2027
- lrps.every((lrp) => hadRobRedemption(lrp, sysParams)),
2028
- ).toBeTruthy();
2029
- }
2030
- });
2031
-
2032
- test<MyContext>('Open 2.5x leveraged CDP 4 LRPs price ~103.973621; f_r=.01; f_m=.03', async (context: MyContext) => {
2033
- context.lucid.selectWallet.fromSeed(context.users.admin.seedPhrase);
2034
-
2035
- const [sysParams, [iusdAssetInfo]] = await init(context.lucid, [
2036
- {
2037
- ...iusdInitialAssetCfg(),
2038
- collateralAssets: [
2039
- {
2040
- ...mkBaseCollateralAsset(adaAssetClass, 0n, {
2041
- numerator: 103_973_621n,
2042
- denominator: 1_000_000n,
2043
- }),
2044
- maintenanceRatio: { numerator: 15n, denominator: 10n },
2045
- },
2046
- ],
2047
- debtMintingFeeRatio: { numerator: 3n, denominator: 100n },
2048
- redemptionReimbursementRatio: { numerator: 1n, denominator: 100n },
2049
- },
2050
- ]);
2051
-
2052
- await openBuyRobs(
2053
- context,
2054
- sysParams,
2055
- iusdAssetInfo.iassetTokenNameAscii,
2056
- adaAssetClass,
2057
- [400_000_000n, 400_000_000n, 400_000_000n, 400_000_000n],
2058
- { numerator: 150n, denominator: 1n },
2059
- );
2060
-
2061
- const allLrps = await findAllRobs(
2062
- context.lucid,
2063
- sysParams,
2064
- iusdAssetInfo.iassetTokenNameAscii,
2065
- );
2066
-
2067
- const orefs = await findAllNecessaryOrefs(
2068
- context.lucid,
2069
- sysParams,
2070
- iusdAssetInfo.iassetTokenNameAscii,
2071
- adaAssetClass,
2072
- );
2073
-
2074
- const priceOracleUtxo = await findPriceOracleFromCollateralAsset(
2075
- context.lucid,
2076
- orefs.collateralAsset,
2077
- );
2078
-
2079
- if (priceOracleUtxo == null) {
2080
- throw new Error('Expected oracle UTXO');
2081
- }
2082
-
2083
- const baseCollateral = 1_000_000_000n;
2084
- await runAndAwaitTx(
2085
- context.lucid,
2086
- leverageCdpWithRob(
2087
- 2.5,
2088
- baseCollateral,
2089
- priceOracleUtxo,
2090
- orefs.iasset.utxo,
2091
- orefs.collateralAsset.utxo,
2092
- orefs.cdpCreatorUtxo,
2093
- orefs.interestOracleUtxo,
2094
- orefs.treasuryUtxo,
2095
- sysParams,
2096
- context.lucid,
2097
- allLrps.map((lrps) => [lrps.utxo, lrps.datum]),
2098
- ),
2099
- );
2100
-
2101
- const [pkh, skh] = await addrDetails(context.lucid);
2102
-
2103
- const res = await findCdp(
2104
- context.lucid,
2105
- sysParams.validatorHashes.cdpHash,
2106
- fromSystemParamsAsset(sysParams.cdpParams.cdpAuthToken),
2107
- pkh.hash,
2108
- skh,
2109
- );
2110
-
2111
- // Assert leverage
2112
- assertValueInRange(
2113
- Number(lovelacesAmt(res.utxo.assets)) / Number(baseCollateral),
2114
- {
2115
- min: 2.4999,
2116
- max: 2.5,
2117
- },
2118
- );
2119
-
2120
- // Assert collateral ratio
2121
- assertValueInRange(
2122
- cdpCollateralRatioPercentage(
2123
- BigInt(context.lucid.slotToUnixTime(context.lucid.currentSlot())),
2124
- parsePriceOracleDatum(getInlineDatumOrThrow(priceOracleUtxo)).price,
2125
- res.utxo.assets,
2126
- res.datum,
2127
- parseInterestOracleDatum(
2128
- getInlineDatumOrThrow(orefs.interestOracleUtxo),
2129
- ),
2130
- ),
2131
- {
2132
- min: 160,
2133
- max: 160.1,
2134
- },
2135
- );
2136
-
2137
- {
2138
- const lrps = await findAllRobs(
2139
- context.lucid,
2140
- sysParams,
2141
- iusdAssetInfo.iassetTokenNameAscii,
2142
- );
2143
- expect(
2144
- lrps.every((lrp) => hadRobRedemption(lrp, sysParams)),
2145
- ).toBeTruthy();
2146
- }
2147
- });
2148
-
2149
- test<MyContext>('(non ADA collateral) Open 1.75x leveraged CDP 3 LRPs price ~2.397; f_r=.017; f_m=.0391', async (context: MyContext) => {
2150
- context.lucid.selectWallet.fromSeed(context.users.admin.seedPhrase);
2151
-
2152
- const [sysParams, [iusdAssetInfo]] = await init(context.lucid, [
2153
- {
2154
- ...iusdInitialAssetCfg(),
2155
- collateralAssets: [
2156
- {
2157
- ...mkBaseCollateralAsset(adaAssetClass, 0n, {
2158
- numerator: 1_000_000n,
2159
- denominator: 1_000_000n,
2160
- }),
2161
- maintenanceRatio: { numerator: 15n, denominator: 10n },
2162
- },
2163
- {
2164
- ...mkBaseCollateralAsset(collateralAssetA, 0n, {
2165
- numerator: 2_397_000n,
2166
- denominator: 1_000_000n,
2167
- }),
2168
- maintenanceRatio: { numerator: 15n, denominator: 10n },
2169
- },
2170
- ],
2171
- debtMintingFeeRatio: { numerator: 391n, denominator: 10_000n },
2172
- redemptionReimbursementRatio: { numerator: 17n, denominator: 1000n },
2173
- },
2174
- ]);
2175
-
2176
- await openBuyRobs(
2177
- context,
2178
- sysParams,
2179
- iusdAssetInfo.iassetTokenNameAscii,
2180
- adaAssetClass,
2181
- [400_000_000n, 400_000_000n],
2182
- { numerator: 5n, denominator: 1n },
2183
- );
2184
- await openBuyRobs(
2185
- context,
2186
- sysParams,
2187
- iusdAssetInfo.iassetTokenNameAscii,
2188
- collateralAssetA,
2189
- [450_000_000n, 450_000_000n],
2190
- { numerator: 5n, denominator: 1n },
2191
- );
2192
-
2193
- const allLrps = await findAllRobs(
2194
- context.lucid,
2195
- sysParams,
2196
- iusdAssetInfo.iassetTokenNameAscii,
2197
- );
2198
-
2199
- const orefs = await findAllNecessaryOrefs(
2200
- context.lucid,
2201
- sysParams,
2202
- iusdAssetInfo.iassetTokenNameAscii,
2203
- collateralAssetA,
2204
- );
2205
-
2206
- const priceOracleUtxo = await findPriceOracleFromCollateralAsset(
2207
- context.lucid,
2208
- orefs.collateralAsset,
2209
- );
2210
-
2211
- if (priceOracleUtxo == null) {
2212
- throw new Error('Expected oracle UTXO');
2213
- }
2214
-
2215
- const baseCollateral = 1_000_000_000n;
2216
- await runAndAwaitTx(
2217
- context.lucid,
2218
- leverageCdpWithRob(
2219
- 1.75,
2220
- baseCollateral,
2221
- priceOracleUtxo,
2222
- orefs.iasset.utxo,
2223
- orefs.collateralAsset.utxo,
2224
- orefs.cdpCreatorUtxo,
2225
- orefs.interestOracleUtxo,
2226
- orefs.treasuryUtxo,
2227
- sysParams,
2228
- context.lucid,
2229
- allLrps.map((lrps) => [lrps.utxo, lrps.datum]),
2230
- ),
2231
- );
2232
-
2233
- const [pkh, skh] = await addrDetails(context.lucid);
2234
-
2235
- const res = await findCdp(
2236
- context.lucid,
2237
- sysParams.validatorHashes.cdpHash,
2238
- fromSystemParamsAsset(sysParams.cdpParams.cdpAuthToken),
2239
- pkh.hash,
2240
- skh,
2241
- );
2242
-
2243
- // Assert leverage
2244
- assertValueInRange(
2245
- Number(assetClassValueOf(res.utxo.assets, collateralAssetA)) /
2246
- Number(baseCollateral),
2247
- {
2248
- min: 1.749999,
2249
- max: 1.75,
2250
- },
2251
- );
2252
-
2253
- // Assert collateral ratio
2254
- assertValueInRange(
2255
- cdpCollateralRatioPercentage(
2256
- BigInt(context.lucid.slotToUnixTime(context.lucid.currentSlot())),
2257
- parsePriceOracleDatum(getInlineDatumOrThrow(priceOracleUtxo)).price,
2258
- res.utxo.assets,
2259
- res.datum,
2260
- parseInterestOracleDatum(
2261
- getInlineDatumOrThrow(orefs.interestOracleUtxo),
2262
- ),
2263
- ),
2264
- {
2265
- min: 220,
2266
- max: 220.1,
2267
- },
2268
- );
2269
-
2270
- {
2271
- const lrps = await findAllRobs(
2272
- context.lucid,
2273
- sysParams,
2274
- iusdAssetInfo.iassetTokenNameAscii,
2275
- );
2276
- // All with collateral asset A had redemptions
2277
- expect(
2278
- lrps
2279
- .filter((lrp) =>
2280
- match(lrp.datum.orderType)
2281
- .returnType<boolean>()
2282
- .with({ BuyIAssetOrder: P.select() }, (content) =>
2283
- isSameAssetClass(content.collateralAsset, collateralAssetA),
2284
- )
2285
- .otherwise(() => false),
2286
- )
2287
- .every((lrp) => hadRobRedemption(lrp, sysParams)),
2288
- ).toBeTruthy();
2289
- }
2290
- });
2291
-
2292
- test<MyContext>('Open max leverage leveraged CDP; 4 CDPs; price 1; f_r=.01; f_m=.005', async (context: MyContext) => {
2293
- context.lucid.selectWallet.fromSeed(context.users.admin.seedPhrase);
2294
-
2295
- const [sysParams, [iusdAssetInfo]] = await init(context.lucid, [
2296
- {
2297
- ...iusdInitialAssetCfg(),
2298
- collateralAssets: [
2299
- {
2300
- ...mkBaseCollateralAsset(adaAssetClass, 0n, {
2301
- numerator: 1n,
2302
- denominator: 1n,
2303
- }),
2304
- maintenanceRatio: { numerator: 15n, denominator: 10n },
2305
- },
2306
- ],
2307
- debtMintingFeeRatio: { numerator: 5n, denominator: 1_000n },
2308
- redemptionReimbursementRatio: { numerator: 1n, denominator: 100n },
2309
- },
2310
- ]);
2311
-
2312
- await openBuyRobs(
2313
- context,
2314
- sysParams,
2315
- iusdAssetInfo.iassetTokenNameAscii,
2316
- adaAssetClass,
2317
- [500_000_000n, 500_000_000n, 500_000_000n, 500_000_000n],
2318
- { numerator: 15n, denominator: 10n },
2319
- );
2320
-
2321
- const allLrps = await findAllRobs(
2322
- context.lucid,
2323
- sysParams,
2324
- iusdAssetInfo.iassetTokenNameAscii,
2325
- );
2326
-
2327
- const orefs = await findAllNecessaryOrefs(
2328
- context.lucid,
2329
- sysParams,
2330
- iusdAssetInfo.iassetTokenNameAscii,
2331
- adaAssetClass,
2332
- );
2333
-
2334
- const priceOracleUtxo = await findPriceOracleFromCollateralAsset(
2335
- context.lucid,
2336
- orefs.collateralAsset,
2337
- );
2338
-
2339
- if (priceOracleUtxo == null) {
2340
- throw new Error('Expected oracle UTXO');
2341
- }
2342
-
2343
- const baseCollateral = 1_000_000_000n;
2344
- const maxLeverage = calculateLeverageFromCollateralRatio(
2345
- fromHex(fromText(iusdAssetInfo.iassetTokenNameAscii)),
2346
- adaAssetClass,
2347
- orefs.collateralAsset.datum.maintenanceRatio,
2348
- baseCollateral,
2349
- parsePriceOracleDatum(getInlineDatumOrThrow(priceOracleUtxo)).price,
2350
- orefs.iasset.datum.debtMintingFeeRatio,
2351
- orefs.iasset.datum.redemptionProcessingFeeRatio,
2352
- allLrps.map((lrps) => [lrps.utxo, lrps.datum]),
2353
- )!;
2354
-
2355
- await benchmarkAndAwaitTx(
2356
- 'Leverage - CDP open with 4 LRP',
2357
- await leverageCdpWithRob(
2358
- maxLeverage,
2359
- baseCollateral,
2360
- priceOracleUtxo,
2361
- orefs.iasset.utxo,
2362
- orefs.collateralAsset.utxo,
2363
- orefs.cdpCreatorUtxo,
2364
- orefs.interestOracleUtxo,
2365
- orefs.treasuryUtxo,
2366
- sysParams,
2367
- context.lucid,
2368
- allLrps.map((lrps) => [lrps.utxo, lrps.datum]),
2369
- ),
2370
- context.lucid,
2371
- context.emulator,
2372
- );
2373
-
2374
- const [pkh, skh] = await addrDetails(context.lucid);
2375
-
2376
- const res = await findCdp(
2377
- context.lucid,
2378
- sysParams.validatorHashes.cdpHash,
2379
- fromSystemParamsAsset(sysParams.cdpParams.cdpAuthToken),
2380
- pkh.hash,
2381
- skh,
2382
- );
2383
-
2384
- // Assert leverage
2385
- assertValueInRange(
2386
- Number(lovelacesAmt(res.utxo.assets)) / Number(baseCollateral),
2387
- {
2388
- min: 2.9126,
2389
- max: 2.9127,
2390
- },
2391
- );
2392
-
2393
- // Assert collateral ratio
2394
- assertValueInRange(
2395
- cdpCollateralRatioPercentage(
2396
- BigInt(context.lucid.slotToUnixTime(context.lucid.currentSlot())),
2397
- parsePriceOracleDatum(getInlineDatumOrThrow(priceOracleUtxo)).price,
2398
- res.utxo.assets,
2399
- res.datum,
2400
- parseInterestOracleDatum(
2401
- getInlineDatumOrThrow(orefs.interestOracleUtxo),
2402
- ),
2403
- ),
2404
- {
2405
- min:
2406
- rationalToFloat(orefs.collateralAsset.datum.maintenanceRatio) * 100,
2407
- max:
2408
- rationalToFloat(orefs.collateralAsset.datum.maintenanceRatio) * 100 +
2409
- 1,
2410
- },
2411
- );
2412
-
2413
- {
2414
- const lrps = await findAllRobs(
2415
- context.lucid,
2416
- sysParams,
2417
- iusdAssetInfo.iassetTokenNameAscii,
2418
- );
2419
- expect(
2420
- lrps.every((lrp) => hadRobRedemption(lrp, sysParams)),
2421
- ).toBeTruthy();
2422
- }
2423
- });
2424
-
2425
- test<MyContext>('Open max leverage leveraged CDP; 2 CDPs; price 2.5; f_r=.014; f_m=.006', async (context: MyContext) => {
2426
- context.lucid.selectWallet.fromSeed(context.users.admin.seedPhrase);
2427
-
2428
- const [sysParams, [iusdAssetInfo]] = await init(context.lucid, [
2429
- {
2430
- ...iusdInitialAssetCfg(),
2431
- collateralAssets: [
2432
- {
2433
- ...mkBaseCollateralAsset(adaAssetClass, 0n, {
2434
- numerator: 25n,
2435
- denominator: 10n,
2436
- }),
2437
- maintenanceRatio: { numerator: 13n, denominator: 10n },
2438
- },
2439
- ],
2440
- debtMintingFeeRatio: { numerator: 6n, denominator: 1_000n },
2441
- redemptionReimbursementRatio: { numerator: 14n, denominator: 1000n },
2442
- },
2443
- ]);
2444
-
2445
- await openBuyRobs(
2446
- context,
2447
- sysParams,
2448
- iusdAssetInfo.iassetTokenNameAscii,
2449
- adaAssetClass,
2450
- [325_000_000n, 325_000_000n],
2451
- { numerator: 3n, denominator: 1n },
2452
- );
2453
-
2454
- const allLrps = await findAllRobs(
2455
- context.lucid,
2456
- sysParams,
2457
- iusdAssetInfo.iassetTokenNameAscii,
2458
- );
2459
-
2460
- const orefs = await findAllNecessaryOrefs(
2461
- context.lucid,
2462
- sysParams,
2463
- iusdAssetInfo.iassetTokenNameAscii,
2464
- adaAssetClass,
2465
- );
2466
-
2467
- const priceOracleUtxo = await findPriceOracleFromCollateralAsset(
2468
- context.lucid,
2469
- orefs.collateralAsset,
2470
- );
2471
-
2472
- if (priceOracleUtxo == null) {
2473
- throw new Error('Expected oracle UTXO');
2474
- }
2475
-
2476
- const baseCollateral = 200_000_000n;
2477
- const maxLeverage = calculateLeverageFromCollateralRatio(
2478
- fromHex(fromText(iusdAssetInfo.iassetTokenNameAscii)),
2479
- adaAssetClass,
2480
- orefs.collateralAsset.datum.maintenanceRatio,
2481
- baseCollateral,
2482
- parsePriceOracleDatum(getInlineDatumOrThrow(priceOracleUtxo)).price,
2483
- orefs.iasset.datum.debtMintingFeeRatio,
2484
- orefs.iasset.datum.redemptionReimbursementRatio,
2485
- allLrps.map((lrps) => [lrps.utxo, lrps.datum]),
2486
- )!;
2487
-
2488
- await runAndAwaitTx(
2489
- context.lucid,
2490
- leverageCdpWithRob(
2491
- maxLeverage,
2492
- baseCollateral,
2493
- priceOracleUtxo,
2494
- orefs.iasset.utxo,
2495
- orefs.collateralAsset.utxo,
2496
- orefs.cdpCreatorUtxo,
2497
- orefs.interestOracleUtxo,
2498
- orefs.treasuryUtxo,
2499
- sysParams,
2500
- context.lucid,
2501
- allLrps.map((lrps) => [lrps.utxo, lrps.datum]),
2502
- ),
2503
- );
2504
-
2505
- const [pkh, skh] = await addrDetails(context.lucid);
2506
-
2507
- const res = await findCdp(
2508
- context.lucid,
2509
- sysParams.validatorHashes.cdpHash,
2510
- fromSystemParamsAsset(sysParams.cdpParams.cdpAuthToken),
2511
- pkh.hash,
2512
- skh,
2513
- );
2514
-
2515
- // Assert leverage
2516
- assertValueInRange(
2517
- Number(lovelacesAmt(res.utxo.assets)) / Number(baseCollateral),
2518
- {
2519
- min: 4.0625,
2520
- max: 4.06251,
2521
- },
2522
- );
2523
-
2524
- // Assert collateral ratio
2525
- assertValueInRange(
2526
- cdpCollateralRatioPercentage(
2527
- BigInt(context.lucid.slotToUnixTime(context.lucid.currentSlot())),
2528
- parsePriceOracleDatum(getInlineDatumOrThrow(priceOracleUtxo)).price,
2529
- res.utxo.assets,
2530
- res.datum,
2531
- parseInterestOracleDatum(
2532
- getInlineDatumOrThrow(orefs.interestOracleUtxo),
2533
- ),
2534
- ),
2535
- {
2536
- min:
2537
- rationalToFloat(orefs.collateralAsset.datum.maintenanceRatio) * 100,
2538
- max:
2539
- rationalToFloat(orefs.collateralAsset.datum.maintenanceRatio) * 100 +
2540
- 1,
2541
- },
2542
- );
2543
-
2544
- {
2545
- const lrps = await findAllRobs(
2546
- context.lucid,
2547
- sysParams,
2548
- iusdAssetInfo.iassetTokenNameAscii,
2549
- );
2550
- expect(
2551
- lrps.every((lrp) => hadRobRedemption(lrp, sysParams)),
2552
- ).toBeTruthy();
2553
- }
2554
- });
2555
- });