Skip to content

Commit dc4adbf

Browse files
committed
Gate manualLiquidation by EParticipant entitlement
Change `manualLiquidation` access from `access(all)` to `access(EParticipant)` so callers must hold an authorized Pool capability. Update the production transaction and the test-only chosen-vault transaction to borrow the pool via an EParticipant-entitled capability from storage instead of the public path. Grant the EParticipant cap to liquidator accounts in all liquidation test calls. https://claude.ai/code/session_01EScbPupCZD9LkCBWvQDaQ4
1 parent 519b6d0 commit dc4adbf

4 files changed

Lines changed: 29 additions & 9 deletions

File tree

cadence/contracts/FlowALPv0.cdc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1977,7 +1977,7 @@ access(all) contract FlowALPv0 {
19771977
/// - C means collateral: Ce is effective collateral, Ct is true collateral, measured in $
19781978
/// - D means debt: De is effective debt, Dt is true debt, measured in $
19791979
/// - Fc, Fd are collateral and debt factors
1980-
access(all) fun manualLiquidation(
1980+
access(EParticipant) fun manualLiquidation(
19811981
pid: UInt64,
19821982
debtType: Type,
19831983
seizeType: Type,

cadence/tests/liquidation_phase1_test.cdc

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ fun testManualLiquidation_healthyPosition() {
7575
// Repay MOET to seize FLOW
7676
let repayAmount = 2.0
7777
let seizeAmount = 1.0
78+
grantBetaPoolParticipantAccess(PROTOCOL_ACCOUNT, liquidator)
7879
let liqRes = _executeTransaction(
7980
"../transactions/flow-alp/pool-management/manual_liquidation.cdc",
8081
[pid, Type<@MOET.Vault>().identifier, FLOW_TOKEN_IDENTIFIER, seizeAmount, repayAmount],
@@ -126,6 +127,7 @@ fun testManualLiquidation_liquidationExceedsTargetHealth() {
126127
// TODO(jord): add helper to compute health boundaries given best acceptable price, then test boundaries
127128
let repayAmount = 500.0
128129
let seizeAmount = 500.0
130+
grantBetaPoolParticipantAccess(PROTOCOL_ACCOUNT, liquidator)
129131
let liqRes = _executeTransaction(
130132
"../transactions/flow-alp/pool-management/manual_liquidation.cdc",
131133
[pid, Type<@MOET.Vault>().identifier, FLOW_TOKEN_IDENTIFIER, seizeAmount, repayAmount],
@@ -186,6 +188,7 @@ fun testManualLiquidation_repayExceedsDebt() {
186188
// Repay MOET to seize FLOW. Choose repay amount above debt balance
187189
let repayAmount = debtBalance + 0.001
188190
let seizeAmount = (repayAmount / newPrice) * 0.99
191+
grantBetaPoolParticipantAccess(PROTOCOL_ACCOUNT, liquidator)
189192
let liqRes = _executeTransaction(
190193
"../transactions/flow-alp/pool-management/manual_liquidation.cdc",
191194
[pid, Type<@MOET.Vault>().identifier, FLOW_TOKEN_IDENTIFIER, seizeAmount, repayAmount],
@@ -244,6 +247,7 @@ fun testManualLiquidation_seizeExceedsCollateral() {
244247
// Repay MOET to seize FLOW. Choose seize amount above collateral balance
245248
let seizeAmount = collateralBalance + 0.001
246249
let repayAmount = seizeAmount * newPrice * 1.01
250+
grantBetaPoolParticipantAccess(PROTOCOL_ACCOUNT, liquidator)
247251
let liqRes = _executeTransaction(
248252
"../transactions/flow-alp/pool-management/manual_liquidation.cdc",
249253
[pid, Type<@MOET.Vault>().identifier, FLOW_TOKEN_IDENTIFIER, seizeAmount, repayAmount],
@@ -303,6 +307,7 @@ fun testManualLiquidation_reduceHealth() {
303307
// Repay MOET to seize FLOW. Choose seize amount above collateral balance
304308
let seizeAmount = collateralBalancePreLiq - 0.01
305309
let repayAmount = seizeAmount * newPrice * 1.01
310+
grantBetaPoolParticipantAccess(PROTOCOL_ACCOUNT, liquidator)
306311
let liqRes = _executeTransaction(
307312
"../transactions/flow-alp/pool-management/manual_liquidation.cdc",
308313
[pid, Type<@MOET.Vault>().identifier, FLOW_TOKEN_IDENTIFIER, seizeAmount, repayAmount],
@@ -366,6 +371,7 @@ fun testManualLiquidation_increaseHealthBelowTarget() {
366371
// Liquidator offers 150 FLOW < 200 FLOW (better price)
367372
let repayAmount = 100.0
368373
let seizeAmount = 150.0
374+
grantBetaPoolParticipantAccess(PROTOCOL_ACCOUNT, liquidator)
369375
let liqRes = _executeTransaction(
370376
"../transactions/flow-alp/pool-management/manual_liquidation.cdc",
371377
[pid, Type<@MOET.Vault>().identifier, FLOW_TOKEN_IDENTIFIER, seizeAmount, repayAmount],
@@ -431,6 +437,7 @@ fun testManualLiquidation_liquidateToTarget() {
431437
// Liquidator offers 33.66 FLOW < 142.86 FLOW (better price)
432438
let repayAmount = 100.0
433439
let seizeAmount = 33.66
440+
grantBetaPoolParticipantAccess(PROTOCOL_ACCOUNT, liquidator)
434441
let liqRes = _executeTransaction(
435442
"../transactions/flow-alp/pool-management/manual_liquidation.cdc",
436443
[pid, Type<@MOET.Vault>().identifier, FLOW_TOKEN_IDENTIFIER, seizeAmount, repayAmount],
@@ -488,6 +495,7 @@ fun testManualLiquidation_repaymentVaultCollateralType() {
488495
// Purport to repay MOET to seize FLOW, but we will actually pass in a FLOW vault for repayment
489496
let repayAmount = debtBalance + 0.001
490497
let seizeAmount = (repayAmount / newPrice) * 0.99
498+
grantBetaPoolParticipantAccess(PROTOCOL_ACCOUNT, liquidator)
491499
let liqRes = _executeTransaction(
492500
"../tests/transactions/flow-alp/pool-management/manual_liquidation_chosen_vault.cdc",
493501
[pid, Type<@MOET.Vault>().identifier, FLOW_TOKEN_IDENTIFIER, FLOW_TOKEN_IDENTIFIER, seizeAmount, repayAmount],
@@ -544,6 +552,7 @@ fun testManualLiquidation_repaymentVaultTypeMismatch() {
544552
// Purport to repay MOET to seize FLOW, but we will actually pass in a MockYieldToken vault for repayment
545553
let repayAmount = debtBalance + 0.001
546554
let seizeAmount = (repayAmount / newPrice) * 0.99
555+
grantBetaPoolParticipantAccess(PROTOCOL_ACCOUNT, liquidator)
547556
let liqRes = _executeTransaction(
548557
"../tests/transactions/flow-alp/pool-management/manual_liquidation_chosen_vault.cdc",
549558
[pid, Type<@MOET.Vault>().identifier, MOCK_YIELD_TOKEN_IDENTIFIER, FLOW_TOKEN_IDENTIFIER, seizeAmount, repayAmount],
@@ -599,6 +608,7 @@ fun testManualLiquidation_unsupportedDebtType() {
599608
// Pass in MockYieldToken as repayment, an unsupported debt type
600609
let repayAmount = debtBalance + 0.001
601610
let seizeAmount = (repayAmount / newPrice) * 0.99
611+
grantBetaPoolParticipantAccess(PROTOCOL_ACCOUNT, liquidator)
602612
let liqRes = _executeTransaction(
603613
"../tests/transactions/flow-alp/pool-management/manual_liquidation_chosen_vault.cdc",
604614
[pid, MOCK_YIELD_TOKEN_IDENTIFIER, MOCK_YIELD_TOKEN_IDENTIFIER, FLOW_TOKEN_IDENTIFIER, seizeAmount, repayAmount],
@@ -654,6 +664,7 @@ fun testManualLiquidation_unsupportedCollateralType() {
654664
// Repay MOET to seize FLOW. Choose seize amount above collateral balance
655665
let seizeAmount = collateralBalancePreLiq - 0.01
656666
let repayAmount = seizeAmount * newPrice * 1.01
667+
grantBetaPoolParticipantAccess(PROTOCOL_ACCOUNT, liquidator)
657668
let liqRes = _executeTransaction(
658669
"../transactions/flow-alp/pool-management/manual_liquidation.cdc",
659670
[pid, Type<@MOET.Vault>().identifier, MOCK_YIELD_TOKEN_IDENTIFIER, seizeAmount, repayAmount],
@@ -738,6 +749,7 @@ fun testManualLiquidation_supportedDebtTypeNotInPosition() {
738749
// user1 has no MockYieldToken debt balance
739750
let seizeAmount = 0.01
740751
let repayAmount = 100.0
752+
grantBetaPoolParticipantAccess(PROTOCOL_ACCOUNT, liquidator)
741753
let liqRes = _executeTransaction(
742754
"../transactions/flow-alp/pool-management/manual_liquidation.cdc",
743755
[pid1, MOCK_YIELD_TOKEN_IDENTIFIER, FLOW_TOKEN_IDENTIFIER, seizeAmount, repayAmount],
@@ -822,6 +834,7 @@ fun testManualLiquidation_supportedCollateralTypeNotInPosition() {
822834
// User1 only has MOET debt, not MockYieldToken debt
823835
let seizeAmount = 0.01
824836
let repayAmount = 100.0
837+
grantBetaPoolParticipantAccess(PROTOCOL_ACCOUNT, liquidator)
825838
let liqRes = _executeTransaction(
826839
"../transactions/flow-alp/pool-management/manual_liquidation.cdc",
827840
[pid1, Type<@MOET.Vault>().identifier, MOCK_YIELD_TOKEN_IDENTIFIER, seizeAmount, repayAmount],
@@ -881,6 +894,7 @@ fun testManualLiquidation_dexOraclePriceDivergence_withinThreshold() {
881894
// Liquidator offers 72 FLOW < 73.53 FLOW (better price)
882895
let repayAmount = 50.0
883896
let seizeAmount = 72.0
897+
grantBetaPoolParticipantAccess(PROTOCOL_ACCOUNT, liquidator)
884898
let liqRes = _executeTransaction(
885899
"../transactions/flow-alp/pool-management/manual_liquidation.cdc",
886900
[pid, Type<@MOET.Vault>().identifier, FLOW_TOKEN_IDENTIFIER, seizeAmount, repayAmount],
@@ -917,6 +931,7 @@ fun testManualLiquidation_dexOraclePriceDivergence_dexBelowOracle() {
917931
setupMoetVault(liquidator, beFailed: false)
918932
mintMoet(signer: Test.getAccount(0x0000000000000007), to: liquidator.address, amount: 1000.0, beFailed: false)
919933

934+
grantBetaPoolParticipantAccess(PROTOCOL_ACCOUNT, liquidator)
920935
let liqRes = _executeTransaction(
921936
"../transactions/flow-alp/pool-management/manual_liquidation.cdc",
922937
[pid, Type<@MOET.Vault>().identifier, FLOW_TOKEN_IDENTIFIER, 70.0, 50.0],
@@ -954,6 +969,7 @@ fun testManualLiquidation_dexOraclePriceDivergence_dexAboveOracle() {
954969
setupMoetVault(liquidator, beFailed: false)
955970
mintMoet(signer: Test.getAccount(0x0000000000000007), to: liquidator.address, amount: 1000.0, beFailed: false)
956971

972+
grantBetaPoolParticipantAccess(PROTOCOL_ACCOUNT, liquidator)
957973
let liqRes = _executeTransaction(
958974
"../transactions/flow-alp/pool-management/manual_liquidation.cdc",
959975
[pid, Type<@MOET.Vault>().identifier, FLOW_TOKEN_IDENTIFIER, 66.0, 50.0],
@@ -1005,6 +1021,7 @@ fun testManualLiquidation_liquidatorOfferWorseThanDex() {
10051021
// Liquidator offers 75 FLOW > 71.43 FLOW (worse price)
10061022
let repayAmount = 50.0
10071023
let seizeAmount = 75.0
1024+
grantBetaPoolParticipantAccess(PROTOCOL_ACCOUNT, liquidator)
10081025
let liqRes = _executeTransaction(
10091026
"../transactions/flow-alp/pool-management/manual_liquidation.cdc",
10101027
[pid, Type<@MOET.Vault>().identifier, FLOW_TOKEN_IDENTIFIER, seizeAmount, repayAmount],
@@ -1058,6 +1075,7 @@ fun testManualLiquidation_combinedEdgeCase() {
10581075
// But divergence is 9.375% which exceeds 3% threshold
10591076
let repayAmount = 50.0
10601077
let seizeAmount = 75.0
1078+
grantBetaPoolParticipantAccess(PROTOCOL_ACCOUNT, liquidator)
10611079
let liqRes = _executeTransaction(
10621080
"../transactions/flow-alp/pool-management/manual_liquidation.cdc",
10631081
[pid, Type<@MOET.Vault>().identifier, FLOW_TOKEN_IDENTIFIER, seizeAmount, repayAmount],

cadence/tests/transactions/flow-alp/pool-management/manual_liquidation_chosen_vault.cdc

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,18 @@ import "FlowALPv0"
1010
/// debtVaultIdentifier: e.g., Type<@MOET.Vault>().identifier
1111
/// seizeVaultIdentifier: e.g., Type<@FlowToken.Vault>().identifier
1212
transaction(pid: UInt64, purportedDebtVaultIdentifier: String, actualDebtVaultIdentifier: String, seizeVaultIdentifier: String, seizeAmount: UFix64, repayAmount: UFix64) {
13-
let pool: &FlowALPv0.Pool
13+
let pool: auth(FlowALPv0.EParticipant) &FlowALPv0.Pool
1414
let receiver: &{FungibleToken.Receiver}
1515
let actualDebtType: Type
1616
let purportedDebtType: Type
1717
let seizeType: Type
1818
let repay: @{FungibleToken.Vault}
1919

2020
prepare(signer: auth(BorrowValue, SaveValue, IssueStorageCapabilityController, PublishCapability, UnpublishCapability) &Account) {
21-
let protocolAddress = Type<@FlowALPv0.Pool>().address!
22-
self.pool = getAccount(protocolAddress).capabilities.borrow<&FlowALPv0.Pool>(FlowALPv0.PoolPublicPath)
23-
?? panic("Could not borrow Pool at \(FlowALPv0.PoolPublicPath)")
21+
let cap = signer.storage.borrow<&Capability<auth(FlowALPv0.EParticipant, FlowALPv0.EPosition) &FlowALPv0.Pool>>(
22+
from: FlowALPv0.PoolCapStoragePath
23+
) ?? panic("Could not borrow Pool capability from storage - ensure the signer has been granted Pool access with EParticipant entitlement")
24+
self.pool = cap.borrow() ?? panic("Could not borrow Pool from capability")
2425

2526
// Resolve types
2627
self.actualDebtType = CompositeType(actualDebtVaultIdentifier) ?? panic("Invalid actualDebtVaultIdentifier: \(actualDebtVaultIdentifier)")

cadence/transactions/flow-alp/pool-management/manual_liquidation.cdc

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,17 @@ import "FlowALPv0"
99
/// debtVaultIdentifier: e.g., Type<@MOET.Vault>().identifier
1010
/// seizeVaultIdentifier: e.g., Type<@FlowToken.Vault>().identifier
1111
transaction(pid: UInt64, debtVaultIdentifier: String, seizeVaultIdentifier: String, seizeAmount: UFix64, repayAmount: UFix64) {
12-
let pool: &FlowALPv0.Pool
12+
let pool: auth(FlowALPv0.EParticipant) &FlowALPv0.Pool
1313
let receiver: &{FungibleToken.Receiver}
1414
let debtType: Type
1515
let seizeType: Type
1616
let repay: @{FungibleToken.Vault}
1717

1818
prepare(signer: auth(BorrowValue, SaveValue, IssueStorageCapabilityController, PublishCapability, UnpublishCapability) &Account) {
19-
let protocolAddress = Type<@FlowALPv0.Pool>().address!
20-
self.pool = getAccount(protocolAddress).capabilities.borrow<&FlowALPv0.Pool>(FlowALPv0.PoolPublicPath)
21-
?? panic("Could not borrow Pool at \(FlowALPv0.PoolPublicPath)")
19+
let cap = signer.storage.borrow<&Capability<auth(FlowALPv0.EParticipant, FlowALPv0.EPosition) &FlowALPv0.Pool>>(
20+
from: FlowALPv0.PoolCapStoragePath
21+
) ?? panic("Could not borrow Pool capability from storage - ensure the signer has been granted Pool access with EParticipant entitlement")
22+
self.pool = cap.borrow() ?? panic("Could not borrow Pool from capability")
2223

2324
// Resolve types
2425
self.debtType = CompositeType(debtVaultIdentifier) ?? panic("Invalid debtVaultIdentifier: \(debtVaultIdentifier)")

0 commit comments

Comments
 (0)