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