Skip to content

Commit 68c0681

Browse files
authored
Merge pull request #262 from onflow/UlianaAndrukhiv/180-interest-rate-testing
Interest Rate Boundary Conditions Testing
2 parents 68cff90 + 78b1104 commit 68c0681

18 files changed

+834
-178
lines changed

cadence/contracts/FlowALPModels.cdc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -553,7 +553,7 @@ access(all) contract FlowALPModels {
553553
effectiveDebt: {Type: UFix128}
554554
) {
555555
// Enforce single balance per token invariant: if a type appears in one map, it must not appear in the other.
556-
for collateralType in effectiveCollateral {
556+
for collateralType in effectiveCollateral.keys {
557557
assert(effectiveDebt[collateralType] == nil, message: "cannot construct BalanceSheet: observed both credit and debit balance for \(collateralType.identifier)")
558558
}
559559

cadence/tests/adversarial_recursive_withdraw_source_test.cdc

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,10 +119,13 @@ fun testRecursiveWithdrawSource() {
119119
//
120120
// In this test, the topUpSource behavior is adversarial: it attempts to re-enter
121121
// the pool during the pull/deposit flow. We expect the transaction to fail.
122-
let withdrawRes = executeTransaction(
123-
"./transactions/flow-alp/epositionadmin/withdraw_from_position.cdc",
124-
[positionID, flowTokenIdentifier, 1500.0, true], // pullFromTopUpSource: true
125-
userAccount
122+
let withdrawRes = withdrawFromPosition(
123+
signer: userAccount,
124+
positionId: positionID,
125+
tokenTypeIdentifier: flowTokenIdentifier,
126+
receiverVaultStoragePath: FLOW_VAULT_STORAGE_PATH,
127+
amount: 1500.0,
128+
pullFromTopUpSource: true
126129
)
127130
Test.expect(withdrawRes, Test.beFailed())
128131

cadence/tests/adversarial_type_spoofing_test.cdc

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,13 @@ fun testMaliciousSource() {
5858
Test.expect(openRes, Test.beSucceeded())
5959

6060
// withdraw 1337 Flow from the position
61-
let withdrawRes = executeTransaction(
62-
"./transactions/flow-alp/epositionadmin/withdraw_from_position.cdc",
63-
[1 as UInt64, flowTokenIdentifier, 1337.0, true],
64-
hackerAccount
61+
let withdrawRes = withdrawFromPosition(
62+
signer: hackerAccount,
63+
positionId: 1,
64+
tokenTypeIdentifier: flowTokenIdentifier,
65+
receiverVaultStoragePath: FLOW_VAULT_STORAGE_PATH,
66+
amount: 1337.0,
67+
pullFromTopUpSource: true
6568
)
6669
Test.expect(withdrawRes, Test.beFailed())
6770

cadence/tests/governance_parameters_test.cdc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ fun test_setGovernanceParams_and_exercise_paths() {
1717
// 1) Set insurance swapper
1818
let res = setInsuranceSwapper(
1919
signer: PROTOCOL_ACCOUNT,
20-
tokenTypeIdentifier: MOET_TOKEN_IDENTIFIER,
20+
swapperInTypeIdentifier: MOET_TOKEN_IDENTIFIER,
21+
swapperOutTypeIdentifier: MOET_TOKEN_IDENTIFIER,
2122
priceRatio: 1.0,
2223
)
2324
Test.expect(res, Test.beSucceeded())

cadence/tests/insurance_collection_formula_test.cdc

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,12 @@ fun test_collectInsurance_success_fullAmount() {
5858
mintMoet(signer: PROTOCOL_ACCOUNT, to: PROTOCOL_ACCOUNT.address, amount: 10000.0, beFailed: false)
5959

6060
// configure insurance swapper (1:1 ratio)
61-
let swapperResult = setInsuranceSwapper(signer: PROTOCOL_ACCOUNT, tokenTypeIdentifier: MOET_TOKEN_IDENTIFIER, priceRatio: 1.0)
61+
let swapperResult = setInsuranceSwapper(
62+
signer: PROTOCOL_ACCOUNT,
63+
swapperInTypeIdentifier: MOET_TOKEN_IDENTIFIER,
64+
swapperOutTypeIdentifier: MOET_TOKEN_IDENTIFIER,
65+
priceRatio: 1.0,
66+
)
6267
Test.expect(swapperResult, Test.beSucceeded())
6368

6469
// set 10% annual debit rate

cadence/tests/insurance_collection_test.cdc

Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,12 @@ fun test_collectInsurance_zeroDebitBalance_returnsNil() {
8787
mintMoet(signer: PROTOCOL_ACCOUNT, to: PROTOCOL_ACCOUNT.address, amount: 10000.0, beFailed: false)
8888

8989
// configure insurance swapper (1:1 ratio)
90-
let swapperResult = setInsuranceSwapper(signer: PROTOCOL_ACCOUNT, tokenTypeIdentifier: MOET_TOKEN_IDENTIFIER, priceRatio: 1.0)
90+
let swapperResult = setInsuranceSwapper(
91+
signer: PROTOCOL_ACCOUNT,
92+
swapperInTypeIdentifier: MOET_TOKEN_IDENTIFIER,
93+
swapperOutTypeIdentifier: MOET_TOKEN_IDENTIFIER,
94+
priceRatio: 1.0,
95+
)
9196
Test.expect(swapperResult, Test.beSucceeded())
9297

9398
// verify initial insurance fund balance is 0
@@ -112,7 +117,7 @@ fun test_collectInsurance_zeroDebitBalance_returnsNil() {
112117
access(all)
113118
fun test_collectInsurance_insufficientReserves() {
114119
// configure insurance swapper (1:1 ratio)
115-
let swapperResult = setInsuranceSwapper(signer: PROTOCOL_ACCOUNT, tokenTypeIdentifier: MOET_TOKEN_IDENTIFIER, priceRatio: 1.0)
120+
let swapperResult = setInsuranceSwapper(signer: PROTOCOL_ACCOUNT, swapperInTypeIdentifier: MOET_TOKEN_IDENTIFIER, swapperOutTypeIdentifier: MOET_TOKEN_IDENTIFIER, priceRatio: 1.0)
116121
Test.expect(swapperResult, Test.beSucceeded())
117122

118123
// set 90% annual debit rate
@@ -192,7 +197,12 @@ fun test_collectInsurance_tinyAmount_roundsToZero_returnsNil() {
192197
mintMoet(signer: PROTOCOL_ACCOUNT, to: PROTOCOL_ACCOUNT.address, amount: 10000.0, beFailed: false)
193198

194199
// configure insurance swapper with very low rate
195-
let swapperResult = setInsuranceSwapper(signer: PROTOCOL_ACCOUNT, tokenTypeIdentifier: MOET_TOKEN_IDENTIFIER, priceRatio: 1.0)
200+
let swapperResult = setInsuranceSwapper(
201+
signer: PROTOCOL_ACCOUNT,
202+
swapperInTypeIdentifier: MOET_TOKEN_IDENTIFIER,
203+
swapperOutTypeIdentifier: MOET_TOKEN_IDENTIFIER,
204+
priceRatio: 1.0,
205+
)
196206
Test.expect(swapperResult, Test.beSucceeded())
197207

198208
// set a very low insurance rate
@@ -242,7 +252,12 @@ fun test_collectInsurance_success_fullAmount() {
242252
mintMoet(signer: PROTOCOL_ACCOUNT, to: PROTOCOL_ACCOUNT.address, amount: 10000.0, beFailed: false)
243253

244254
// configure insurance swapper (1:1 ratio)
245-
let swapperResult = setInsuranceSwapper(signer: PROTOCOL_ACCOUNT, tokenTypeIdentifier: MOET_TOKEN_IDENTIFIER, priceRatio: 1.0)
255+
let swapperResult = setInsuranceSwapper(
256+
signer: PROTOCOL_ACCOUNT,
257+
swapperInTypeIdentifier: MOET_TOKEN_IDENTIFIER,
258+
swapperOutTypeIdentifier: MOET_TOKEN_IDENTIFIER,
259+
priceRatio: 1.0,
260+
)
246261
Test.expect(swapperResult, Test.beSucceeded())
247262

248263
// set 10% annual debit rate
@@ -328,10 +343,20 @@ fun test_collectInsurance_multipleTokens() {
328343
mintMoet(signer: PROTOCOL_ACCOUNT, to: PROTOCOL_ACCOUNT.address, amount: 20000.0, beFailed: false)
329344

330345
// configure insurance swappers for both tokens (both swap to MOET at 1:1)
331-
let moetSwapperResult = setInsuranceSwapper(signer: PROTOCOL_ACCOUNT, tokenTypeIdentifier: MOET_TOKEN_IDENTIFIER, priceRatio: 1.0)
346+
let moetSwapperResult = setInsuranceSwapper(
347+
signer: PROTOCOL_ACCOUNT,
348+
swapperInTypeIdentifier: MOET_TOKEN_IDENTIFIER,
349+
swapperOutTypeIdentifier: MOET_TOKEN_IDENTIFIER,
350+
priceRatio: 1.0,
351+
)
332352
Test.expect(moetSwapperResult, Test.beSucceeded())
333353

334-
let flowSwapperResult = setInsuranceSwapper(signer: PROTOCOL_ACCOUNT, tokenTypeIdentifier: FLOW_TOKEN_IDENTIFIER, priceRatio: 1.0)
354+
let flowSwapperResult = setInsuranceSwapper(
355+
signer: PROTOCOL_ACCOUNT,
356+
swapperInTypeIdentifier: FLOW_TOKEN_IDENTIFIER,
357+
swapperOutTypeIdentifier: MOET_TOKEN_IDENTIFIER,
358+
priceRatio: 1.0,
359+
)
335360
Test.expect(flowSwapperResult, Test.beSucceeded())
336361

337362
// set 10% annual debit rates
@@ -431,7 +456,12 @@ fun test_collectInsurance_dexOracleSlippageProtection() {
431456

432457
// Oracle says FLOW = 1.0 MOET (already set in setup())
433458
// Configure insurance swapper with price ratio = 0.5 (50% deviation from oracle)
434-
let swapperResult = setInsuranceSwapper(signer: PROTOCOL_ACCOUNT, tokenTypeIdentifier: FLOW_TOKEN_IDENTIFIER, priceRatio: 0.5)
459+
let swapperResult = setInsuranceSwapper(
460+
signer: PROTOCOL_ACCOUNT,
461+
swapperInTypeIdentifier: FLOW_TOKEN_IDENTIFIER,
462+
swapperOutTypeIdentifier: MOET_TOKEN_IDENTIFIER,
463+
priceRatio: 0.5,
464+
)
435465
Test.expect(swapperResult, Test.beSucceeded())
436466

437467
// set 10% annual debit rate and 10% insurance rate
@@ -451,7 +481,12 @@ fun test_collectInsurance_dexOracleSlippageProtection() {
451481
Test.assertEqual(0.0, balanceAfterFailure)
452482

453483
// Now reconfigure swapper with price ratio = 1.0 (matches oracle, 0% deviation)
454-
let swapperResult2 = setInsuranceSwapper(signer: PROTOCOL_ACCOUNT, tokenTypeIdentifier: FLOW_TOKEN_IDENTIFIER, priceRatio: 1.0)
484+
let swapperResult2 = setInsuranceSwapper(
485+
signer: PROTOCOL_ACCOUNT,
486+
swapperInTypeIdentifier: FLOW_TOKEN_IDENTIFIER,
487+
swapperOutTypeIdentifier: MOET_TOKEN_IDENTIFIER,
488+
priceRatio: 1.0,
489+
)
455490
Test.expect(swapperResult2, Test.beSucceeded())
456491

457492
// collect insurance for FLOW - should SUCCEED now
@@ -472,7 +507,7 @@ fun test_collectInsurance_midPeriodRateChange() {
472507
// configure the protocol FLOW wallet and the insurance swapper
473508
setupMoetVault(PROTOCOL_ACCOUNT, beFailed: false)
474509
mintMoet(signer: PROTOCOL_ACCOUNT, to: PROTOCOL_ACCOUNT.address, amount: 10000.0, beFailed: false)
475-
let swapperResult = setInsuranceSwapper(signer: PROTOCOL_ACCOUNT, tokenTypeIdentifier: FLOW_TOKEN_IDENTIFIER, priceRatio: 1.0)
510+
let swapperResult = setInsuranceSwapper(signer: PROTOCOL_ACCOUNT, swapperInTypeIdentifier: FLOW_TOKEN_IDENTIFIER, swapperOutTypeIdentifier: MOET_TOKEN_IDENTIFIER, priceRatio: 1.0)
476511
Test.expect(swapperResult, Test.beSucceeded())
477512

478513
// set interest curve

cadence/tests/insurance_rate_test.cdc

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ access(all)
1111
fun setup() {
1212
deployContracts()
1313
createAndStorePool(signer: PROTOCOL_ACCOUNT, defaultTokenIdentifier: MOET_TOKEN_IDENTIFIER, beFailed: false)
14-
1514
// take snapshot first, then advance time so reset() target is always lower than current height
1615
snapshot = getCurrentBlockHeight()
1716
// move time by 1 second so Test.reset() works properly before each test
@@ -32,7 +31,8 @@ fun test_setInsuranceRate_withoutEGovernanceEntitlement() {
3231
// set insurance swapper
3332
var res = setInsuranceSwapper(
3433
signer: PROTOCOL_ACCOUNT,
35-
tokenTypeIdentifier: MOET_TOKEN_IDENTIFIER,
34+
swapperInTypeIdentifier: MOET_TOKEN_IDENTIFIER,
35+
swapperOutTypeIdentifier: MOET_TOKEN_IDENTIFIER,
3636
priceRatio: 1.0,
3737
)
3838
Test.expect(res, Test.beSucceeded())
@@ -56,7 +56,8 @@ fun test_setInsuranceRate_withEGovernanceEntitlement() {
5656
// set insurance swapper
5757
var res = setInsuranceSwapper(
5858
signer: PROTOCOL_ACCOUNT,
59-
tokenTypeIdentifier: MOET_TOKEN_IDENTIFIER,
59+
swapperInTypeIdentifier: MOET_TOKEN_IDENTIFIER,
60+
swapperOutTypeIdentifier: MOET_TOKEN_IDENTIFIER,
6061
priceRatio: 1.0,
6162
)
6263
Test.expect(res, Test.beSucceeded())
@@ -104,7 +105,8 @@ fun test_setInsuranceRate_rateGreaterThanOne_fails() {
104105
// set insurance swapper
105106
var res = setInsuranceSwapper(
106107
signer: PROTOCOL_ACCOUNT,
107-
tokenTypeIdentifier: MOET_TOKEN_IDENTIFIER,
108+
swapperInTypeIdentifier: MOET_TOKEN_IDENTIFIER,
109+
swapperOutTypeIdentifier: MOET_TOKEN_IDENTIFIER,
108110
priceRatio: 1.0,
109111
)
110112
Test.expect(res, Test.beSucceeded())
@@ -131,7 +133,8 @@ fun test_setInsuranceRate_combinedRateExceedsOne_fails() {
131133
// set insurance swapper
132134
var res = setInsuranceSwapper(
133135
signer: PROTOCOL_ACCOUNT,
134-
tokenTypeIdentifier: MOET_TOKEN_IDENTIFIER,
136+
swapperInTypeIdentifier: MOET_TOKEN_IDENTIFIER,
137+
swapperOutTypeIdentifier: MOET_TOKEN_IDENTIFIER,
135138
priceRatio: 1.0,
136139
)
137140
Test.expect(res, Test.beSucceeded())
@@ -164,7 +167,8 @@ fun test_setStabilityFeeRate_combinedRateExceedsOne_fails() {
164167
// set insurance swapper
165168
var res = setInsuranceSwapper(
166169
signer: PROTOCOL_ACCOUNT,
167-
tokenTypeIdentifier: MOET_TOKEN_IDENTIFIER,
170+
swapperInTypeIdentifier: MOET_TOKEN_IDENTIFIER,
171+
swapperOutTypeIdentifier: MOET_TOKEN_IDENTIFIER,
168172
priceRatio: 1.0,
169173
)
170174
Test.expect(res, Test.beSucceeded())
@@ -197,7 +201,8 @@ fun test_setInsuranceRate_rateLessThanZero_fails() {
197201
// set insurance swapper
198202
var res = setInsuranceSwapper(
199203
signer: PROTOCOL_ACCOUNT,
200-
tokenTypeIdentifier: MOET_TOKEN_IDENTIFIER,
204+
swapperInTypeIdentifier: MOET_TOKEN_IDENTIFIER,
205+
swapperOutTypeIdentifier: MOET_TOKEN_IDENTIFIER,
201206
priceRatio: 1.0,
202207
)
203208
Test.expect(res, Test.beSucceeded())
@@ -223,7 +228,8 @@ fun test_setInsuranceRate_invalidTokenType_fails() {
223228
// set insurance swapper
224229
var res = setInsuranceSwapper(
225230
signer: PROTOCOL_ACCOUNT,
226-
tokenTypeIdentifier: MOET_TOKEN_IDENTIFIER,
231+
swapperInTypeIdentifier: MOET_TOKEN_IDENTIFIER,
232+
swapperOutTypeIdentifier: MOET_TOKEN_IDENTIFIER,
227233
priceRatio: 1.0,
228234
)
229235
Test.expect(res, Test.beSucceeded())

cadence/tests/insurance_swapper_test.cdc

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ access(all)
2020
fun test_setInsuranceSwapper_success() {
2121
let res = setInsuranceSwapper(
2222
signer: PROTOCOL_ACCOUNT,
23-
tokenTypeIdentifier: MOET_TOKEN_IDENTIFIER,
23+
swapperInTypeIdentifier: MOET_TOKEN_IDENTIFIER,
24+
swapperOutTypeIdentifier: MOET_TOKEN_IDENTIFIER,
2425
priceRatio: 1.0,
2526
)
2627
Test.expect(res, Test.beSucceeded())
@@ -39,7 +40,8 @@ fun test_setInsuranceSwapper_updateExistingSwapper_success() {
3940
let initialPriceRatio = 1.0
4041
let res = setInsuranceSwapper(
4142
signer: PROTOCOL_ACCOUNT,
42-
tokenTypeIdentifier: MOET_TOKEN_IDENTIFIER,
43+
swapperInTypeIdentifier: MOET_TOKEN_IDENTIFIER,
44+
swapperOutTypeIdentifier: MOET_TOKEN_IDENTIFIER,
4345
priceRatio: initialPriceRatio,
4446
)
4547
Test.expect(res, Test.beSucceeded())
@@ -48,7 +50,8 @@ fun test_setInsuranceSwapper_updateExistingSwapper_success() {
4850
let updatedPriceRatio = 2.0
4951
let updatedRes = setInsuranceSwapper(
5052
signer: PROTOCOL_ACCOUNT,
51-
tokenTypeIdentifier: MOET_TOKEN_IDENTIFIER,
53+
swapperInTypeIdentifier: MOET_TOKEN_IDENTIFIER,
54+
swapperOutTypeIdentifier: MOET_TOKEN_IDENTIFIER,
5255
priceRatio: updatedPriceRatio,
5356
)
5457
Test.expect(updatedRes, Test.beSucceeded())
@@ -66,7 +69,8 @@ fun test_removeInsuranceSwapper_success() {
6669
// set a swapper
6770
let res = setInsuranceSwapper(
6871
signer: PROTOCOL_ACCOUNT,
69-
tokenTypeIdentifier: MOET_TOKEN_IDENTIFIER,
72+
swapperInTypeIdentifier: MOET_TOKEN_IDENTIFIER,
73+
swapperOutTypeIdentifier: MOET_TOKEN_IDENTIFIER,
7074
priceRatio: 1.0,
7175
)
7276
Test.expect(res, Test.beSucceeded())
@@ -94,7 +98,8 @@ fun test_remove_insuranceSwapper_failed() {
9498
// set a swapper
9599
var res = setInsuranceSwapper(
96100
signer: PROTOCOL_ACCOUNT,
97-
tokenTypeIdentifier: MOET_TOKEN_IDENTIFIER,
101+
swapperInTypeIdentifier: MOET_TOKEN_IDENTIFIER,
102+
swapperOutTypeIdentifier: MOET_TOKEN_IDENTIFIER,
98103
priceRatio: 1.0,
99104
)
100105
Test.expect(res, Test.beSucceeded())
@@ -130,7 +135,8 @@ access(all)
130135
fun test_setInsuranceSwapper_withoutEGovernanceEntitlement_fails() {
131136
let res = setInsuranceSwapper(
132137
signer: alice,
133-
tokenTypeIdentifier: MOET_TOKEN_IDENTIFIER,
138+
swapperInTypeIdentifier: MOET_TOKEN_IDENTIFIER,
139+
swapperOutTypeIdentifier: MOET_TOKEN_IDENTIFIER,
134140
priceRatio: 1.0,
135141
)
136142

@@ -148,7 +154,8 @@ fun test_setInsuranceSwapper_invalidTokenTypeIdentifier_fails() {
148154

149155
let res = setInsuranceSwapper(
150156
signer: PROTOCOL_ACCOUNT,
151-
tokenTypeIdentifier: invalidTokenIdentifier,
157+
swapperInTypeIdentifier: invalidTokenIdentifier,
158+
swapperOutTypeIdentifier: MOET_TOKEN_IDENTIFIER,
152159
priceRatio: 1.0,
153160
)
154161

@@ -166,7 +173,8 @@ fun test_setInsuranceSwapper_emptyTokenTypeIdentifier_fails() {
166173

167174
let res = setInsuranceSwapper(
168175
signer: PROTOCOL_ACCOUNT,
169-
tokenTypeIdentifier: emptyTokenIdentifier,
176+
swapperInTypeIdentifier: emptyTokenIdentifier,
177+
swapperOutTypeIdentifier: MOET_TOKEN_IDENTIFIER,
170178
priceRatio: 1.0,
171179
)
172180

0 commit comments

Comments
 (0)