Skip to content

Commit 497cbb0

Browse files
authored
Merge branch 'main' into holyfuchs/rebalancer-refactor
2 parents 399ab8e + d29bc11 commit 497cbb0

7 files changed

Lines changed: 119 additions & 106 deletions

File tree

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,3 @@ coverage.json
77
/.pr-body.md
88
/.github/pr_bodies/
99
lcov.info
10-
.flow-fork-cache

cadence/contracts/FlowALPModels.cdc

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1037,13 +1037,13 @@ access(all) contract FlowALPModels {
10371037
/// (used when deposits are made)
10381038
access(EImplementation) fun consumeDepositCapacity(_ amount: UFix64, pid: UInt64)
10391039

1040-
/// Returns the per-deposit limit based on depositCapacity * depositLimitFraction
1041-
/// Rationale: cap per-deposit size to a fraction of the time-based
1042-
/// depositCapacity so a single large deposit cannot monopolize capacity.
1040+
/// Returns the per-deposit limit based on user deposit limit and available deposit capacity.
1041+
/// Rationale: cap per-deposit size to a fraction of the total depositCapacityCap
1042+
/// so a single large deposit cannot monopolize capacity.
10431043
/// Excess is queued and drained in chunks (see asyncUpdatePosition),
10441044
/// enabling fair throughput across many deposits in a block. The 5%
10451045
/// fraction is conservative and can be tuned by protocol parameters.
1046-
access(EImplementation) view fun depositLimit(): UFix64
1046+
access(EImplementation) view fun depositLimit(pid: UInt64): UFix64
10471047

10481048
/// Updates interest indices and regenerates deposit capacity for elapsed time
10491049
access(EImplementation) fun updateForTimeChange()
@@ -1376,9 +1376,15 @@ access(all) contract FlowALPModels {
13761376
)
13771377
}
13781378

1379-
/// Returns the per-deposit limit based on depositCapacity * depositLimitFraction.
1380-
access(EImplementation) view fun depositLimit(): UFix64 {
1381-
return self.depositCapacity * self.depositLimitFraction
1379+
/// Returns the maximum amount that can be deposited to the given position without being queued.
1380+
access(EImplementation) view fun depositLimit(pid: UInt64): UFix64 {
1381+
let userCap = self.getUserDepositLimitCap()
1382+
let userUsed = self.getDepositUsageForPosition(pid)
1383+
var available = userCap - userUsed
1384+
if self.depositCapacity < available {
1385+
available = self.depositCapacity
1386+
}
1387+
return available
13821388
}
13831389

13841390
/// Updates interest indices and regenerates deposit capacity for elapsed time.

cadence/contracts/FlowALPPositionResources.cdc

Lines changed: 56 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,6 @@ import "FlowALPModels"
77

88
access(all) contract FlowALPPositionResources {
99

10-
/// A single authorized Capability to the Pool, shared across all Position resources.
11-
/// Issued once at pool creation time to avoid per-position capability controller bloat.
12-
access(self) var poolCap: Capability<auth(FlowALPModels.EPosition) &{FlowALPModels.PositionPool}>?
13-
14-
/// Sets the contract-level pool capability. Called once by FlowALPv0 when the Pool is created.
15-
access(account) fun setPoolCap(cap: Capability<auth(FlowALPModels.EPosition) &{FlowALPModels.PositionPool}>) {
16-
FlowALPPositionResources.poolCap = cap
17-
}
18-
19-
access(self) fun borrowPool(): auth(FlowALPModels.EPosition) &{FlowALPModels.PositionPool} {
20-
return self.poolCap!.borrow()!
21-
}
22-
2310
/// Position
2411
///
2512
/// A Position is a resource representing ownership of value deposited to the protocol.
@@ -36,13 +23,24 @@ access(all) contract FlowALPPositionResources {
3623
/// The unique ID of the Position used to track deposits and withdrawals to the Pool
3724
access(all) let id: UInt64
3825

39-
init(id: UInt64) {
26+
/// An authorized Capability to the Pool for which this Position was opened.
27+
access(self) let pool: Capability<auth(FlowALPModels.EPosition) &{FlowALPModels.PositionPool}>
28+
29+
init(
30+
id: UInt64,
31+
pool: Capability<auth(FlowALPModels.EPosition) &{FlowALPModels.PositionPool}>
32+
) {
33+
pre {
34+
pool.check():
35+
"Invalid Pool Capability provided - cannot construct Position"
36+
}
4037
self.id = id
38+
self.pool = pool
4139
}
4240

4341
/// Returns the balances (both positive and negative) for all tokens in this position.
4442
access(all) fun getBalances(): [FlowALPModels.PositionBalance] {
45-
let pool = FlowALPPositionResources.borrowPool()
43+
let pool = self.pool.borrow()!
4644
return pool.getPositionDetails(pid: self.id).balances
4745
}
4846

@@ -51,55 +49,55 @@ access(all) contract FlowALPPositionResources {
5149
/// below its min health. If pullFromTopUpSource is false, the calculation will return the balance currently
5250
/// available without topping up the position.
5351
access(all) fun availableBalance(type: Type, pullFromTopUpSource: Bool): UFix64 {
54-
let pool = FlowALPPositionResources.borrowPool()
52+
let pool = self.pool.borrow()!
5553
return pool.availableBalance(pid: self.id, type: type, pullFromTopUpSource: pullFromTopUpSource)
5654
}
5755

5856
/// Returns the current health of the position
5957
access(all) fun getHealth(): UFix128 {
60-
let pool = FlowALPPositionResources.borrowPool()
58+
let pool = self.pool.borrow()!
6159
return pool.positionHealth(pid: self.id)
6260
}
6361

6462
/// Returns the Position's target health (unitless ratio ≥ 1.0)
6563
access(all) fun getTargetHealth(): UFix64 {
66-
let pool = FlowALPPositionResources.borrowPool()
64+
let pool = self.pool.borrow()!
6765
let pos = pool.borrowPosition(pid: self.id)
6866
return FlowALPMath.toUFix64Round(pos.getTargetHealth())
6967
}
7068

7169
/// Sets the target health of the Position
7270
access(FlowALPModels.EPositionAdmin) fun setTargetHealth(targetHealth: UFix64) {
73-
let pool = FlowALPPositionResources.borrowPool()
71+
let pool = self.pool.borrow()!
7472
let pos = pool.borrowPosition(pid: self.id)
7573
pos.setTargetHealth(UFix128(targetHealth))
7674
}
7775

7876
/// Returns the minimum health of the Position
7977
access(all) fun getMinHealth(): UFix64 {
80-
let pool = FlowALPPositionResources.borrowPool()
78+
let pool = self.pool.borrow()!
8179
let pos = pool.borrowPosition(pid: self.id)
8280
return FlowALPMath.toUFix64Round(pos.getMinHealth())
8381
}
8482

8583
/// Sets the minimum health of the Position
8684
access(FlowALPModels.EPositionAdmin) fun setMinHealth(minHealth: UFix64) {
87-
let pool = FlowALPPositionResources.borrowPool()
85+
let pool = self.pool.borrow()!
8886
let pos = pool.borrowPosition(pid: self.id)
8987
pos.setMinHealth(UFix128(minHealth))
9088
pool.queuePositionForUpdateIfNecessary(pid: self.id)
9189
}
9290

9391
/// Returns the maximum health of the Position
9492
access(all) fun getMaxHealth(): UFix64 {
95-
let pool = FlowALPPositionResources.borrowPool()
93+
let pool = self.pool.borrow()!
9694
let pos = pool.borrowPosition(pid: self.id)
9795
return FlowALPMath.toUFix64Round(pos.getMaxHealth())
9896
}
9997

10098
/// Sets the maximum health of the position
10199
access(FlowALPModels.EPositionAdmin) fun setMaxHealth(maxHealth: UFix64) {
102-
let pool = FlowALPPositionResources.borrowPool()
100+
let pool = self.pool.borrow()!
103101
let pos = pool.borrowPosition(pid: self.id)
104102
pos.setMaxHealth(UFix128(maxHealth))
105103
pool.queuePositionForUpdateIfNecessary(pid: self.id)
@@ -127,7 +125,7 @@ access(all) contract FlowALPPositionResources {
127125
from: @{FungibleToken.Vault},
128126
pushToDrawDownSink: Bool
129127
) {
130-
let pool = FlowALPPositionResources.borrowPool()
128+
let pool = self.pool.borrow()!
131129
pool.depositAndPush(
132130
pid: self.id,
133131
from: <-from,
@@ -152,7 +150,7 @@ access(all) contract FlowALPPositionResources {
152150
amount: UFix64,
153151
pullFromTopUpSource: Bool
154152
): @{FungibleToken.Vault} {
155-
let pool = FlowALPPositionResources.borrowPool()
153+
let pool = self.pool.borrow()!
156154
return <- pool.withdrawAndPull(
157155
pid: self.id,
158156
type: type,
@@ -183,8 +181,10 @@ access(all) contract FlowALPPositionResources {
183181
type: Type,
184182
pushToDrawDownSink: Bool
185183
): {DeFiActions.Sink} {
184+
let pool = self.pool.borrow()!
186185
return PositionSink(
187186
id: self.id,
187+
pool: self.pool,
188188
type: type,
189189
pushToDrawDownSink: pushToDrawDownSink
190190
)
@@ -212,8 +212,10 @@ access(all) contract FlowALPPositionResources {
212212
type: Type,
213213
pullFromTopUpSource: Bool
214214
): {DeFiActions.Source} {
215+
let pool = self.pool.borrow()!
215216
return PositionSource(
216217
id: self.id,
218+
pool: self.pool,
217219
type: type,
218220
pullFromTopUpSource: pullFromTopUpSource
219221
)
@@ -230,7 +232,7 @@ access(all) contract FlowALPPositionResources {
230232
///
231233
/// Pass nil to configure the position to not push tokens when the Position exceeds its maximum health.
232234
access(FlowALPModels.EPositionAdmin) fun provideSink(sink: {DeFiActions.Sink}?) {
233-
let pool = FlowALPPositionResources.borrowPool()
235+
let pool = self.pool.borrow()!
234236
pool.lockPosition(self.id)
235237
let pos = pool.borrowPosition(pid: self.id)
236238
pos.setDrawDownSink(sink)
@@ -246,7 +248,7 @@ access(all) contract FlowALPPositionResources {
246248
///
247249
/// Pass nil to configure the position to not pull tokens.
248250
access(FlowALPModels.EPositionAdmin) fun provideSource(source: {DeFiActions.Source}?) {
249-
let pool = FlowALPPositionResources.borrowPool()
251+
let pool = self.pool.borrow()!
250252
pool.lockPosition(self.id)
251253
let pos = pool.borrowPosition(pid: self.id)
252254
pos.setTopUpSource(source)
@@ -262,7 +264,7 @@ access(all) contract FlowALPPositionResources {
262264
/// of either cannot accept/provide sufficient funds for rebalancing, the rebalance will still occur but will
263265
/// not cause the position to reach its target health.
264266
access(FlowALPModels.EPosition | FlowALPModels.ERebalance) fun rebalance(force: Bool) {
265-
let pool = FlowALPPositionResources.borrowPool()
267+
let pool = self.pool.borrow()!
266268
pool.rebalancePosition(pid: self.id, force: force)
267269
}
268270
}
@@ -320,8 +322,11 @@ access(all) contract FlowALPPositionResources {
320322

321323
/// Creates and returns a new Position resource.
322324
/// This remains account-scoped so only the protocol account can mint canonical wrappers.
323-
access(account) fun createPosition(id: UInt64): @Position {
324-
return <- create Position(id: id)
325+
access(account) fun createPosition(
326+
id: UInt64,
327+
pool: Capability<auth(FlowALPModels.EPosition) &{FlowALPModels.PositionPool}>
328+
): @Position {
329+
return <- create Position(id: id, pool: pool)
325330
}
326331

327332
/// Creates and returns a new PositionManager resource
@@ -339,6 +344,9 @@ access(all) contract FlowALPPositionResources {
339344
/// An optional DeFiActions.UniqueIdentifier that identifies this Sink with the DeFiActions stack its a part of
340345
access(contract) var uniqueID: DeFiActions.UniqueIdentifier?
341346

347+
/// An authorized Capability on the Pool for which the related Position is in
348+
access(self) let pool: Capability<auth(FlowALPModels.EPosition) &{FlowALPModels.PositionPool}>
349+
342350
/// The ID of the position in the Pool
343351
access(self) let positionID: UInt64
344352

@@ -351,11 +359,13 @@ access(all) contract FlowALPPositionResources {
351359

352360
init(
353361
id: UInt64,
362+
pool: Capability<auth(FlowALPModels.EPosition) &{FlowALPModels.PositionPool}>,
354363
type: Type,
355364
pushToDrawDownSink: Bool
356365
) {
357366
self.uniqueID = nil
358367
self.positionID = id
368+
self.pool = pool
359369
self.type = type
360370
self.pushToDrawDownSink = pushToDrawDownSink
361371
}
@@ -367,20 +377,18 @@ access(all) contract FlowALPPositionResources {
367377

368378
/// Returns the minimum capacity this Sink can accept as deposits
369379
access(all) fun minimumCapacity(): UFix64 {
370-
return FlowALPPositionResources.poolCap?.check() ?? false ? UFix64.max : 0.0
380+
return self.pool.check() ? UFix64.max : 0.0
371381
}
372382

373383
/// Deposits the funds from the provided Vault reference to the related Position
374384
access(all) fun depositCapacity(from: auth(FungibleToken.Withdraw) &{FungibleToken.Vault}) {
375-
if FlowALPPositionResources.poolCap?.check() != true {
376-
return
385+
if let pool = self.pool.borrow() {
386+
pool.depositAndPush(
387+
pid: self.positionID,
388+
from: <-from.withdraw(amount: from.balance),
389+
pushToDrawDownSink: self.pushToDrawDownSink
390+
)
377391
}
378-
let pool = FlowALPPositionResources.borrowPool()
379-
pool.depositAndPush(
380-
pid: self.positionID,
381-
from: <-from.withdraw(amount: from.balance),
382-
pushToDrawDownSink: self.pushToDrawDownSink
383-
)
384392
}
385393

386394
access(all) fun getComponentInfo(): DeFiActions.ComponentInfo {
@@ -410,6 +418,9 @@ access(all) contract FlowALPPositionResources {
410418
/// An optional DeFiActions.UniqueIdentifier that identifies this Sink with the DeFiActions stack its a part of
411419
access(contract) var uniqueID: DeFiActions.UniqueIdentifier?
412420

421+
/// An authorized Capability on the Pool for which the related Position is in
422+
access(self) let pool: Capability<auth(FlowALPModels.EPosition) &{FlowALPModels.PositionPool}>
423+
413424
/// The ID of the position in the Pool
414425
access(self) let positionID: UInt64
415426

@@ -422,11 +433,13 @@ access(all) contract FlowALPPositionResources {
422433

423434
init(
424435
id: UInt64,
436+
pool: Capability<auth(FlowALPModels.EPosition) &{FlowALPModels.PositionPool}>,
425437
type: Type,
426438
pullFromTopUpSource: Bool
427439
) {
428440
self.uniqueID = nil
429441
self.positionID = id
442+
self.pool = pool
430443
self.type = type
431444
self.pullFromTopUpSource = pullFromTopUpSource
432445
}
@@ -438,11 +451,11 @@ access(all) contract FlowALPPositionResources {
438451

439452
/// Returns the minimum available this Source can provide on withdrawal
440453
access(all) fun minimumAvailable(): UFix64 {
441-
if FlowALPPositionResources.poolCap?.check() != true {
454+
if !self.pool.check() {
442455
return 0.0
443456
}
444457

445-
let pool = FlowALPPositionResources.borrowPool()
458+
let pool = self.pool.borrow()!
446459
return pool.availableBalance(
447460
pid: self.positionID,
448461
type: self.type,
@@ -452,11 +465,11 @@ access(all) contract FlowALPPositionResources {
452465

453466
/// Withdraws up to the max amount as the sourceType Vault
454467
access(FungibleToken.Withdraw) fun withdrawAvailable(maxAmount: UFix64): @{FungibleToken.Vault} {
455-
if FlowALPPositionResources.poolCap?.check() != true {
468+
if !self.pool.check() {
456469
return <- DeFiActionsUtils.getEmptyVault(self.type)
457470
}
458471

459-
let pool = FlowALPPositionResources.borrowPool()
472+
let pool = self.pool.borrow()!
460473
let available = pool.availableBalance(
461474
pid: self.positionID,
462475
type: self.type,
@@ -492,8 +505,4 @@ access(all) contract FlowALPPositionResources {
492505
self.uniqueID = id
493506
}
494507
}
495-
496-
init() {
497-
self.poolCap = nil
498-
}
499508
}

0 commit comments

Comments
 (0)