diff --git a/x/stakeibc/keeper/icqcallbacks_callibrate_delegation.go b/x/stakeibc/keeper/icqcallbacks_callibrate_delegation.go index 49abb32078..15235f02c8 100644 --- a/x/stakeibc/keeper/icqcallbacks_callibrate_delegation.go +++ b/x/stakeibc/keeper/icqcallbacks_callibrate_delegation.go @@ -11,6 +11,9 @@ import ( "github.com/Stride-Labs/stride/v15/x/stakeibc/types" ) +// CalibrationThreshold is the max amount of tokens by which a calibration can alter internal record keeping of delegations +var CalibrationThreshold = sdk.NewInt(1000) + // DelegatorSharesCallback is a callback handler for UpdateValidatorSharesExchRate queries. // // In an attempt to get the ICA's delegation amount on a given validator, we have to query: @@ -67,6 +70,12 @@ func CalibrateDelegationCallback(k Keeper, ctx sdk.Context, args []byte, query i } delegationChange := validator.Delegation.Sub(delegatedTokens) + // if the delegation change is more than the calibration threshold constant, log and throw an error + if delegationChange.Abs().GTE(CalibrationThreshold) { + k.Logger(ctx).Info(utils.LogICQCallbackWithHostZone(chainId, ICQCallbackID_Calibrate, + "Delegation change is GT CalibrationThreshold, failing calibration callback")) + return errorsmod.Wrapf(types.ErrCalibrationThresholdExceeded, "calibration threshold %v exceeded, attempted to calibrate by %v ", CalibrationThreshold, delegationChange) + } validator.Delegation = validator.Delegation.Sub(delegationChange) hostZone.TotalDelegations = hostZone.TotalDelegations.Sub(delegationChange) diff --git a/x/stakeibc/keeper/msg_server_submit_tx.go b/x/stakeibc/keeper/msg_server_submit_tx.go index 9c0b881296..2520c259b7 100644 --- a/x/stakeibc/keeper/msg_server_submit_tx.go +++ b/x/stakeibc/keeper/msg_server_submit_tx.go @@ -500,7 +500,7 @@ func (k Keeper) SubmitCalibrationICQ(ctx sdk.Context, hostZone types.HostZone, v if hostZone.DelegationIcaAddress == "" { return errorsmod.Wrapf(types.ErrICAAccountNotFound, "no delegation address found for %s", hostZone.ChainId) } - validator, valIndex, found := GetValidatorFromAddress(hostZone.Validators, validatorAddress) + validator, _, found := GetValidatorFromAddress(hostZone.Validators, validatorAddress) if !found { return errorsmod.Wrapf(types.ErrValidatorNotFound, "no registered validator for address (%s)", validatorAddress) } diff --git a/x/stakeibc/types/errors.go b/x/stakeibc/types/errors.go index a0805b6f3f..939739b8e4 100644 --- a/x/stakeibc/types/errors.go +++ b/x/stakeibc/types/errors.go @@ -57,4 +57,5 @@ var ( ErrLSMLiquidStakeDisabledForHostZone = errorsmod.Register(ModuleName, 1549, "LSM liquid stake is disabled for host zone") ErrUnableToRemoveValidator = errorsmod.Register(ModuleName, 1550, "Unable to remove validator") ErrInvalidBounds = errorsmod.Register(ModuleName, 1551, "Invalid safety bounds - inner bounds must be within outer bounds") + ErrCalibrationThresholdExceeded = errorsmod.Register(ModuleName, 1552, "Calibration threshold exceeded") )