diff --git a/x/staking/keeper/msg_server.go b/x/staking/keeper/msg_server.go index 92d1bed..019e53a 100644 --- a/x/staking/keeper/msg_server.go +++ b/x/staking/keeper/msg_server.go @@ -162,10 +162,10 @@ func (k msgServer) EditValidator(ctx context.Context, msg *types.MsgEditValidato return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "empty description") } - if msg.MinSelfDelegation != nil && !msg.MinSelfDelegation.IsPositive() { + if msg.MinSelfDelegation != nil && msg.MinSelfDelegation.IsNegative() { return nil, errorsmod.Wrap( sdkerrors.ErrInvalidRequest, - "minimum self delegation must be a positive integer", + "minimum self delegation cannot be negative", ) } diff --git a/x/staking/types/msg.go b/x/staking/types/msg.go index 11542a6..b94e0fb 100644 --- a/x/staking/types/msg.go +++ b/x/staking/types/msg.go @@ -57,8 +57,15 @@ func (msg MsgCreateValidator) Validate(ac address.Codec) error { return ErrEmptyValidatorPubKey } - if !msg.Value.IsValid() { - return errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "invalid delegation amount") + // MUKAN FAIR BIRTH: Allow zero self-delegation at genesis. + // Standard Cosmos SDK requires IsValid() which enforces IsPositive(). + // Mukan Network allows validators to join with 0 UMC — they earn stake + // through PoJ mining after the network is live. + if err := sdk.ValidateDenom(msg.Value.Denom); err != nil { + return errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "invalid delegation coin denom") + } + if msg.Value.Amount.IsNegative() { + return errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "self delegation amount cannot be negative") } if msg.Description == (Description{}) { @@ -80,6 +87,8 @@ func (msg MsgCreateValidator) Validate(ac address.Codec) error { ) } + // MUKAN FAIR BIRTH: Zero self-delegation is valid — minimum is enforced at + // the PoJ level, not at the staking layer. if msg.Value.Amount.LT(msg.MinSelfDelegation) { return ErrSelfDelegationBelowMinimum }