diff --git a/sdk/action/client.go b/sdk/action/client.go index 147be819..296cba9c 100644 --- a/sdk/action/client.go +++ b/sdk/action/client.go @@ -298,9 +298,11 @@ func (c *ClientImpl) BuildCascadeMetadataFromFile(ctx context.Context, filePath denom := paramsResp.Params.BaseActionFee.Denom exp := paramsResp.Params.ExpirationDuration - // Compute data size in KB for fee - kb := int(fi.Size()) / 1024 - feeResp, err := c.lumeraClient.GetActionFee(ctx, strconv.Itoa(kb)) + // Compute data size in KB for fee, rounding up to avoid underpaying + // Keep consistent with supernode verification which uses ceil(bytes/1024) + sizeBytes := fi.Size() + kb := (sizeBytes + 1023) / 1024 // int64 division + feeResp, err := c.lumeraClient.GetActionFee(ctx, strconv.FormatInt(kb, 10)) if err != nil { return actiontypes.CascadeMetadata{}, "", "", fmt.Errorf("get action fee: %w", err) } diff --git a/supernode/cascade/helper.go b/supernode/cascade/helper.go index a2006354..2d204c52 100644 --- a/supernode/cascade/helper.go +++ b/supernode/cascade/helper.go @@ -195,13 +195,16 @@ func (task *CascadeRegistrationTask) verifyActionFee(ctx context.Context, action } requiredFee := sdk.NewCoin("ulume", math.NewInt(amount)) logtrace.Debug(ctx, "calculated required fee", logtrace.Fields{"fee": requiredFee.String(), "dataBytes": dataSize}) - if action.Price == nil || action.Price.String() != requiredFee.String() { - got := "" - if action.Price != nil { - got = action.Price.String() - } - return task.wrapErr(ctx, "insufficient fee", errors.Errorf("expected at least %s, got %s", requiredFee.String(), got), fields) + // Accept paying more than the minimum required fee. Only enforce denom match and Amount >= required. + if action.Price == nil { + return task.wrapErr(ctx, "insufficient fee", errors.Errorf("expected at least %s, got ", requiredFee.String()), fields) + } + if action.Price.Denom != requiredFee.Denom { + return task.wrapErr(ctx, "invalid fee denom", errors.Errorf("expected denom %s, got %s", requiredFee.Denom, action.Price.Denom), fields) + } + if action.Price.Amount.LT(requiredFee.Amount) { + return task.wrapErr(ctx, "insufficient fee", errors.Errorf("expected at least %s, got %s", requiredFee.String(), action.Price.String()), fields) } - logtrace.Info(ctx, "register: verify action fee ok", logtrace.Fields{"required_fee": requiredFee.String()}) + logtrace.Info(ctx, "register: verify action fee ok", logtrace.Fields{"required_fee": requiredFee.String(), "provided_fee": action.Price.String()}) return nil }