Skip to content

Commit 9220db6

Browse files
authored
Merge pull request #157 from onflow/fix/FLOW-7-supervisor-reschedule-failure-event
FLOW-7: Emit event on Supervisor rescheduling failure
2 parents db084c4 + 66c8c74 commit 9220db6

File tree

1 file changed

+72
-31
lines changed

1 file changed

+72
-31
lines changed

cadence/contracts/FlowYieldVaultsSchedulerV1.cdc

Lines changed: 72 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,17 @@ access(all) contract FlowYieldVaultsSchedulerV1 {
7373
timestamp: UFix64
7474
)
7575

76+
/// Emitted when Supervisor fails to self-reschedule.
77+
///
78+
/// This is primarily used to surface insufficient fee vault balance, which would otherwise
79+
/// cause the Supervisor to stop monitoring without any on-chain signal.
80+
access(all) event SupervisorRescheduleFailed(
81+
timestamp: UFix64,
82+
requiredFee: UFix64?,
83+
availableBalance: UFix64?,
84+
error: String
85+
)
86+
7687
/// Entitlement to schedule transactions
7788
access(all) entitlement Schedule
7889

@@ -213,10 +224,9 @@ access(all) contract FlowYieldVaultsSchedulerV1 {
213224

214225
// Borrow the AutoBalancer and call scheduleNextRebalance() directly
215226
let autoBalancerRef = scheduleCap!.borrow()!
216-
let scheduleError = autoBalancerRef.scheduleNextRebalance(whileExecuting: nil)
217227

218-
if scheduleError != nil {
219-
emit YieldVaultRecoveryFailed(yieldVaultID: yieldVaultID, error: scheduleError!)
228+
if let scheduleError = autoBalancerRef.scheduleNextRebalance(whileExecuting: nil) {
229+
emit YieldVaultRecoveryFailed(yieldVaultID: yieldVaultID, error: scheduleError)
220230
// Leave in pending queue for retry on next Supervisor run
221231
continue
222232
}
@@ -262,9 +272,24 @@ access(all) contract FlowYieldVaultsSchedulerV1 {
262272
destroy txn
263273

264274
let nextTimestamp = getCurrentBlock().timestamp + recurringInterval
265-
let supervisorCap = FlowYieldVaultsSchedulerRegistry.getSupervisorCap()
266275

267-
if supervisorCap == nil || !supervisorCap!.check() {
276+
let supervisorCap = FlowYieldVaultsSchedulerRegistry.getSupervisorCap()
277+
if supervisorCap == nil {
278+
emit SupervisorRescheduleFailed(
279+
timestamp: nextTimestamp,
280+
requiredFee: nil,
281+
availableBalance: nil,
282+
error: "Missing Supervisor capability"
283+
)
284+
return
285+
}
286+
if !supervisorCap!.check() {
287+
emit SupervisorRescheduleFailed(
288+
timestamp: nextTimestamp,
289+
requiredFee: nil,
290+
availableBalance: nil,
291+
error: "Invalid Supervisor capability"
292+
)
268293
return
269294
}
270295

@@ -276,34 +301,50 @@ access(all) contract FlowYieldVaultsSchedulerV1 {
276301
let baseFee = est.flowFee ?? FlowYieldVaultsSchedulerV1.MIN_FEE_FALLBACK
277302
let required = baseFee * FlowYieldVaultsSchedulerV1.FEE_MARGIN_MULTIPLIER
278303

279-
if let vaultRef = self.feesCap.borrow() {
280-
if vaultRef.balance >= required {
281-
let fees <- vaultRef.withdraw(amount: required) as! @FlowToken.Vault
304+
let vaultRef = self.feesCap.borrow()
305+
if vaultRef == nil {
306+
emit SupervisorRescheduleFailed(
307+
timestamp: nextTimestamp,
308+
requiredFee: required,
309+
availableBalance: nil,
310+
error: "Could not borrow fee vault"
311+
)
312+
return
313+
}
314+
if vaultRef!.balance < required {
315+
emit SupervisorRescheduleFailed(
316+
timestamp: nextTimestamp,
317+
requiredFee: required,
318+
availableBalance: vaultRef!.balance,
319+
error: "Insufficient fee vault balance"
320+
)
321+
return
322+
}
282323

283-
let nextData: {String: AnyStruct} = {
284-
"priority": priority.rawValue,
285-
"executionEffort": executionEffort,
286-
"recurringInterval": recurringInterval,
287-
"scanForStuck": scanForStuck
288-
}
324+
let fees <- vaultRef!.withdraw(amount: required) as! @FlowToken.Vault
289325

290-
let selfTxn <- FlowTransactionScheduler.schedule(
291-
handlerCap: supervisorCap!,
292-
data: nextData,
293-
timestamp: nextTimestamp,
294-
priority: priority,
295-
executionEffort: executionEffort,
296-
fees: <-fees
297-
)
298-
299-
emit SupervisorRescheduled(
300-
scheduledTransactionID: selfTxn.id,
301-
timestamp: nextTimestamp
302-
)
303-
304-
self._scheduledTransaction <-! selfTxn
305-
}
326+
let nextData = {
327+
"priority": priority.rawValue,
328+
"executionEffort": executionEffort,
329+
"recurringInterval": recurringInterval,
330+
"scanForStuck": scanForStuck
306331
}
332+
333+
let selfTxn <- FlowTransactionScheduler.schedule(
334+
handlerCap: supervisorCap!,
335+
data: nextData,
336+
timestamp: nextTimestamp,
337+
priority: priority,
338+
executionEffort: executionEffort,
339+
fees: <-fees
340+
)
341+
342+
emit SupervisorRescheduled(
343+
scheduledTransactionID: selfTxn.id,
344+
timestamp: nextTimestamp
345+
)
346+
347+
self._scheduledTransaction <-! selfTxn
307348
}
308349

309350
/// Cancels the scheduled transaction if it is scheduled.
@@ -401,7 +442,7 @@ access(all) contract FlowYieldVaultsSchedulerV1 {
401442
access(account) fun enqueuePendingYieldVault(yieldVaultID: UInt64) {
402443
assert(
403444
FlowYieldVaultsSchedulerRegistry.isRegistered(yieldVaultID: yieldVaultID),
404-
message: "enqueuePendingYieldVault: YieldVault #".concat(yieldVaultID.toString()).concat(" is not registered")
445+
message: "enqueuePendingYieldVault: YieldVault #\(yieldVaultID.toString()) is not registered"
405446
)
406447
FlowYieldVaultsSchedulerRegistry.enqueuePending(yieldVaultID: yieldVaultID)
407448
}

0 commit comments

Comments
 (0)