diff --git a/client/x/evmstaking/keeper/validator.go b/client/x/evmstaking/keeper/validator.go index 49a92f19..ca12bed0 100644 --- a/client/x/evmstaking/keeper/validator.go +++ b/client/x/evmstaking/keeper/validator.go @@ -78,53 +78,57 @@ func (k Keeper) ProcessCreateValidator(ctx context.Context, ev *bindings.IPToken } skeeperMsgServer := skeeper.NewMsgServerImpl(evmstakingSKeeper) - _, err = k.stakingKeeper.GetValidator(ctx, validatorAddr) - if err != nil { + if _, err = k.stakingKeeper.GetValidator(ctx, validatorAddr); err == nil { + // TODO(rayden): refund + return errors.New("validator already exists") + } else if !errors.Is(err, stypes.ErrNoValidatorFound) { // Either the validator does not exist, or unknown error. - if !errors.Is(err, stypes.ErrNoValidatorFound) { - return errors.Wrap(err, "get validator") - } - - moniker := ev.Moniker - if moniker == "validator" { - moniker = validatorAddr.String() // use validator address as moniker if not provided (ie. "validator") - } - - var tokenType stypes.TokenType - switch ev.SupportsUnlocked { - case uint8(stypes.TokenType_LOCKED): - tokenType = stypes.TokenType_LOCKED - case uint8(stypes.TokenType_UNLOCKED): - tokenType = stypes.TokenType_UNLOCKED - default: - return errors.New("invalid token type") - } - - // Validator does not exist, create validator with self-delegation. - msg, err := stypes.NewMsgCreateValidator( - validatorAddr.String(), - validatorPubkey, - amountCoin, - stypes.Description{Moniker: moniker}, - stypes.NewCommissionRates( - // Divide these decimals by 100 to convert from basis points to decimal. Will cut off decimal as the rates are integers. - math.LegacyNewDec(int64(ev.CommissionRate)).Quo(math.LegacyNewDec(10000)), - math.LegacyNewDec(int64(ev.MaxCommissionRate)).Quo(math.LegacyNewDec(10000)), - math.LegacyNewDec(int64(ev.MaxCommissionChangeRate)).Quo(math.LegacyNewDec(10000)), - ), - math.NewInt(1), // Stub out minimum self delegation for now, just use 1. - tokenType, - ) - if err != nil { - return errors.Wrap(err, "create validator message") - } - - _, err = skeeperMsgServer.CreateValidator(ctx, msg) - if err != nil { - return errors.Wrap(err, "create validator") - } + return errors.Wrap(err, "get validator") + } + + moniker := ev.Moniker + if moniker == "" { + moniker = validatorAddr.String() // use validator address as moniker if not provided + } + + var tokenType stypes.TokenType + switch ev.SupportsUnlocked { + case uint8(stypes.TokenType_LOCKED): + tokenType = stypes.TokenType_LOCKED + case uint8(stypes.TokenType_UNLOCKED): + tokenType = stypes.TokenType_UNLOCKED + default: + return errors.New("invalid token type") + } + + minSelfDelegation, err := k.stakingKeeper.MinDelegation(ctx) + if err != nil { + return errors.Wrap(err, "get min self delegation") + } + + // Validator does not exist, create validator with self-delegation. + msg, err := stypes.NewMsgCreateValidator( + validatorAddr.String(), + validatorPubkey, + amountCoin, + stypes.Description{Moniker: moniker}, + stypes.NewCommissionRates( + // Divide these decimals by 100 to convert from basis points to decimal. Will cut off decimal as the rates are integers. + math.LegacyNewDec(int64(ev.CommissionRate)).Quo(math.LegacyNewDec(10000)), + math.LegacyNewDec(int64(ev.MaxCommissionRate)).Quo(math.LegacyNewDec(10000)), + math.LegacyNewDec(int64(ev.MaxCommissionChangeRate)).Quo(math.LegacyNewDec(10000)), + ), + minSelfDelegation, // make minimum self delegation align with minimum delegation amount + tokenType, + ) + if err != nil { + return errors.Wrap(err, "create validator message") + } + + _, err = skeeperMsgServer.CreateValidator(ctx, msg) + if err != nil { + return errors.Wrap(err, "create validator") } - // TODO(rayden): refund return nil } diff --git a/client/x/evmstaking/types/expected_keepers.go b/client/x/evmstaking/types/expected_keepers.go index 2de269fa..9a97ef3f 100644 --- a/client/x/evmstaking/types/expected_keepers.go +++ b/client/x/evmstaking/types/expected_keepers.go @@ -6,6 +6,7 @@ import ( "cosmossdk.io/core/address" corestore "cosmossdk.io/core/store" + "cosmossdk.io/math" abci "github.com/cometbft/cometbft/abci/types" sdk "github.com/cosmos/cosmos-sdk/types" @@ -65,6 +66,8 @@ type StakingKeeper interface { EndBlocker(ctx context.Context) ([]abci.ValidatorUpdate, error) EndBlockerWithUnbondedEntries(ctx context.Context) ([]abci.ValidatorUpdate, []stakingtypes.UnbondedEntry, error) + + MinDelegation(ctx context.Context) (math.Int, error) } // SlashingKeeper defines the expected interface for the slashing module.