-
Notifications
You must be signed in to change notification settings - Fork 204
/
hooks.go
88 lines (72 loc) · 3.26 KB
/
hooks.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
package keeper
import (
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types"
epochstypes "github.com/Stride-Labs/stride/v19/x/epochs/types"
)
// This module has the following epochly triggers
// - Handle delegations daily
// - Handle undelegations every 4 days
// - Updates the redemption rate daily
// - Check for completed unbondings hourly
// - Process claims (if applicable) hourly
//
// Note: The hourly processes are meant for actions that should run ASAP,
// but the hourly buffer makes it less expensive
func (k Keeper) BeforeEpochStart(ctx sdk.Context, epochInfo epochstypes.EpochInfo) {
epochNumber := uint64(epochInfo.CurrentEpoch)
// Every day, refresh the redemption rate and prepare delegations
// Every 4 days, prepare undelegations
if epochInfo.Identifier == epochstypes.DAY_EPOCH {
// Update the redemption rate
// If this fails, do not proceed to the delegation or undelegation step
// Note: This must be run first because it is used when refreshing the native token
// balance in prepare undelegation
if err := k.UpdateRedemptionRate(ctx); err != nil {
k.Logger(ctx).Error(fmt.Sprintf("Unable update redemption rate: %s", err.Error()))
return
}
// Post the redemption rate to the oracle (if it doesn't exceed the bounds)
if err := k.PostRedemptionRateToOracles(ctx); err != nil {
k.Logger(ctx).Error(fmt.Sprintf("Unable to post redemption rate to oracle: %s", err.Error()))
}
// Prepare delegations by transferring the deposited tokens to the host zone
if err := k.SafelyPrepareDelegation(ctx, epochNumber, epochInfo.Duration); err != nil {
k.Logger(ctx).Error(fmt.Sprintf("Unable to prepare delegation for epoch %d: %s", epochNumber, err.Error()))
}
// Every few days (depending on the unbonding frequency) prepare undelegations which
// freezes the accumulating unbonding record and refreshes the native token amount
// TODO [cleanup]: replace with unbonding frequency
if epochInfo.CurrentEpoch%4 == 0 {
if err := k.SafelyPrepareUndelegation(ctx, epochNumber); err != nil {
k.Logger(ctx).Error(fmt.Sprintf("Unable to prepare undelegations for epoch %d: %s", epochNumber, err.Error()))
}
}
}
// Every hour, annotate finished unbondings and distribute claims
// The hourly epoch is meant for actions that should be executed asap, but have a
// relaxed SLA. It makes it slightly less expensive than running every block
if epochInfo.Identifier == epochstypes.HOUR_EPOCH {
k.MarkFinishedUnbondings(ctx)
if err := k.SafelyDistributeClaims(ctx); err != nil {
k.Logger(ctx).Error(fmt.Sprintf("Unable to distribute claims for epoch %d: %s", epochNumber, err.Error()))
}
}
// Every mint epoch, liquid stake fees and distribute to fee collector
if epochInfo.Identifier == epochstypes.MINT_EPOCH {
if err := k.SafelyLiquidStakeAndDistributeFees(ctx); err != nil {
k.Logger(ctx).Error(fmt.Sprintf("Unable to liquid stake and distribute fees this epoch %d: %s", epochNumber, err.Error()))
}
}
}
type Hooks struct {
k Keeper
}
var _ epochstypes.EpochHooks = Hooks{}
func (k Keeper) Hooks() Hooks {
return Hooks{k}
}
func (h Hooks) BeforeEpochStart(ctx sdk.Context, epochInfo epochstypes.EpochInfo) {
h.k.BeforeEpochStart(ctx, epochInfo)
}
func (h Hooks) AfterEpochEnd(ctx sdk.Context, epochInfo epochstypes.EpochInfo) {}