diff --git a/app/ante/cosmos/sigverify.go b/app/ante/cosmos/sigverify.go index 84f8cf25a..c6984f308 100644 --- a/app/ante/cosmos/sigverify.go +++ b/app/ante/cosmos/sigverify.go @@ -495,26 +495,9 @@ func ConsumeMultisignatureVerificationGas( meter sdk.GasMeter, sig *signing.MultiSignatureData, pubkey multisig.PubKey, params types.Params, accSeq uint64, ) error { - size := sig.BitArray.Count() - sigIndex := 0 - - for i := 0; i < size; i++ { - if !sig.BitArray.GetIndex(i) { - continue - } - sigV2 := signing.SignatureV2{ - PubKey: pubkey.GetPubKeys()[i], - Data: sig.Signatures[sigIndex], - Sequence: accSeq, - } - err := DefaultSigVerificationGasConsumer(meter, sigV2, params) - if err != nil { - return err - } - sigIndex++ - } - - return nil + return ConsumeMultisignatureVerificationGasWithVerifier( + meter, sig, pubkey, params, accSeq, DefaultSigVerificationGasConsumer, + ) } // GetSignerAcc returns an account for a given address that is expected to sign @@ -580,3 +563,47 @@ func signatureDataToBz(data signing.SignatureData) ([][]byte, error) { return nil, sdkerrors.ErrInvalidType.Wrapf("unexpected signature data type %T", data) } } + +// ConsumeMultisignatureVerificationGasWithVerifier consumes gas from a GasMeter for verifying +// a multisig pubkey signature. It uses the provided verifier function to verify each signature +// and consume gas accordingly. +func ConsumeMultisignatureVerificationGasWithVerifier( + meter sdk.GasMeter, sig *signing.MultiSignatureData, pubkey multisig.PubKey, + params types.Params, accSeq uint64, verifier authante.SignatureVerificationGasConsumer, +) error { + pubkeys := pubkey.GetPubKeys() + size := sig.BitArray.Count() + if size != len(pubkeys) { + return sdkerrors.ErrInvalidPubKey.Wrap( + "bitarray length doesn't match the number of public keys", + ) + } + if len(sig.Signatures) != sig.BitArray.NumTrueBitsBefore(size) { + return sdkerrors.ErrTooManySignatures.Wrap( + "number of signatures doesn't equal the number of true bits in bitarray", + ) + } + // we have verified that size == len(pubkeys) + // and that the number of signatures == number of true bits in the bitarray + // so we can safely iterate over the pubkeys and signatures + sigIndex := 0 + + for i := 0; i < size; i++ { + if !sig.BitArray.GetIndex(i) { + // not signed + continue + } + sigV2 := signing.SignatureV2{ + PubKey: pubkeys[i], + Data: sig.Signatures[sigIndex], + Sequence: accSeq, + } + err := verifier(meter, sigV2, params) + if err != nil { + return err + } + sigIndex++ + } + + return nil +} diff --git a/app/ante/sigverify.go b/app/ante/sigverify.go index e4303d62f..4ed530392 100644 --- a/app/ante/sigverify.go +++ b/app/ante/sigverify.go @@ -4,6 +4,7 @@ import ( "fmt" errorsmod "cosmossdk.io/errors" + cosmosante "github.com/ExocoreNetwork/exocore/app/ante/cosmos" "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" "github.com/cosmos/cosmos-sdk/crypto/types/multisig" sdk "github.com/cosmos/cosmos-sdk/types" @@ -64,35 +65,7 @@ func ConsumeMultisignatureVerificationGas( meter sdk.GasMeter, sig *signing.MultiSignatureData, pubkey multisig.PubKey, params authtypes.Params, accSeq uint64, ) error { - pubkeys := pubkey.GetPubKeys() - size := sig.BitArray.Count() - if size != len(pubkeys) { - return errorsmod.Wrapf(errortypes.ErrInvalidPubKey, "bitarray length doesn't match the number of public keys") - } - if len(sig.Signatures) != sig.BitArray.NumTrueBitsBefore(size) { - return errorsmod.Wrapf(errortypes.ErrTooManySignatures, "number of signatures exceeds number of bits in bitarray") - } - // we have verified that size == len(pubkeys) - // and that the number of signatures == number of true bits in the bitarray - // so we can safely iterate over the pubkeys and signatures - sigIndex := 0 - - for i := 0; i < size; i++ { - if !sig.BitArray.GetIndex(i) { - // not signed - continue - } - sigV2 := signing.SignatureV2{ - PubKey: pubkeys[i], - Data: sig.Signatures[sigIndex], - Sequence: accSeq, - } - err := SigVerificationGasConsumer(meter, sigV2, params) - if err != nil { - return err - } - sigIndex++ - } - - return nil + return cosmosante.ConsumeMultisignatureVerificationGasWithVerifier( + meter, sig, pubkey, params, accSeq, SigVerificationGasConsumer, + ) } diff --git a/app/app.go b/app/app.go index 1eeffa625..f84763c36 100644 --- a/app/app.go +++ b/app/app.go @@ -546,7 +546,10 @@ func NewExocoreApp( ) // asset and client chain registry. - app.AssetsKeeper = assetsKeeper.NewKeeper(keys[assetsTypes.StoreKey], appCodec, &app.OracleKeeper, app.BankKeeper, &app.DelegationKeeper) + app.AssetsKeeper = assetsKeeper.NewKeeper( + keys[assetsTypes.StoreKey], appCodec, &app.OracleKeeper, + app.BankKeeper, &app.DelegationKeeper, authAddrString, + ) // handles delegations by stakers, and must know if the delegatee operator is registered. app.DelegationKeeper = delegationKeeper.NewKeeper( @@ -574,18 +577,17 @@ func NewExocoreApp( // these two modules aren't finalized yet. app.RewardKeeper = rewardKeeper.NewKeeper( appCodec, keys[rewardTypes.StoreKey], app.AssetsKeeper, - app.AVSManagerKeeper, + app.AVSManagerKeeper, authAddrString, ) app.ExoSlashKeeper = slashKeeper.NewKeeper( - appCodec, keys[exoslashTypes.StoreKey], app.AssetsKeeper, + appCodec, keys[exoslashTypes.StoreKey], app.AssetsKeeper, authAddrString, ) // x/oracle is not fully integrated (or enabled) but allows for exchange rates to be added. app.OracleKeeper = oracleKeeper.NewKeeper( appCodec, keys[oracleTypes.StoreKey], memKeys[oracleTypes.MemStoreKey], app.GetSubspace(oracleTypes.ModuleName), app.StakingKeeper, - &app.DelegationKeeper, - &app.AssetsKeeper, + &app.DelegationKeeper, &app.AssetsKeeper, authAddrString, ) // the SDK slashing module is used to slash validators in the case of downtime. it tracks diff --git a/precompiles/reward/reward_test.go b/precompiles/reward/reward_test.go index 3512238b4..548195533 100644 --- a/precompiles/reward/reward_test.go +++ b/precompiles/reward/reward_test.go @@ -83,7 +83,9 @@ func (s *RewardPrecompileTestSuite) TestRunRewardThroughClientChain() { s.Require().NoError(err, "failed to pack input") return s.Address, input } - successRet, err := s.precompile.Methods[reward.MethodReward].Outputs.Pack(true, new(big.Int).Add(depositAmount, withdrawAmount)) + // successRet, err := s.precompile.Methods[reward.MethodReward].Outputs.Pack(true, new(big.Int).Add(depositAmount, withdrawAmount)) + // TODO: reward precompile is disabled, so it always errors and returns fail + successRet, err := s.precompile.Methods[reward.MethodReward].Outputs.Pack(false, new(big.Int)) s.Require().NoError(err) testcases := []struct { name string diff --git a/testutil/keeper/oracle.go b/testutil/keeper/oracle.go index 3316c0b36..4308d54df 100644 --- a/testutil/keeper/oracle.go +++ b/testutil/keeper/oracle.go @@ -14,6 +14,8 @@ import ( "github.com/cosmos/cosmos-sdk/store" storetypes "github.com/cosmos/cosmos-sdk/store/types" sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" typesparams "github.com/cosmos/cosmos-sdk/x/params/types" assetskeeper "github.com/ExocoreNetwork/exocore/x/assets/keeper" @@ -49,6 +51,7 @@ func OracleKeeper(t testing.TB) (*keeper.Keeper, sdk.Context) { dogfoodkeeper.Keeper{}, delegationkeeper.Keeper{}, assetskeeper.Keeper{}, + authtypes.NewModuleAddress(govtypes.ModuleName).String(), ) ctx := sdk.NewContext(stateStore, tmproto.Header{ diff --git a/x/assets/keeper/keeper.go b/x/assets/keeper/keeper.go index e4c324a27..eaddf0e73 100644 --- a/x/assets/keeper/keeper.go +++ b/x/assets/keeper/keeper.go @@ -1,6 +1,8 @@ package keeper import ( + "fmt" + assetstype "github.com/ExocoreNetwork/exocore/x/assets/types" "github.com/cosmos/cosmos-sdk/codec" storetypes "github.com/cosmos/cosmos-sdk/store/types" @@ -13,8 +15,9 @@ type Keeper struct { storeKey storetypes.StoreKey cdc codec.BinaryCodec assetstype.OracleKeeper - bk assetstype.BankKeeper - dk delegationKeeper + bk assetstype.BankKeeper + dk delegationKeeper + authority string } func NewKeeper( @@ -23,13 +26,19 @@ func NewKeeper( oracleKeeper assetstype.OracleKeeper, bk assetstype.BankKeeper, dk delegationKeeper, + authority string, ) Keeper { + // ensure authority is a valid bech32 address + if _, err := sdk.AccAddressFromBech32(authority); err != nil { + panic(fmt.Sprintf("authority address %s is invalid: %s", authority, err)) + } return Keeper{ storeKey: storeKey, cdc: cdc, OracleKeeper: oracleKeeper, bk: bk, dk: dk, + authority: authority, } } diff --git a/x/assets/keeper/msg_server.go b/x/assets/keeper/msg_server.go index 5038f3103..d72f511ae 100644 --- a/x/assets/keeper/msg_server.go +++ b/x/assets/keeper/msg_server.go @@ -3,8 +3,10 @@ package keeper import ( "context" + "github.com/ExocoreNetwork/exocore/utils" assetstype "github.com/ExocoreNetwork/exocore/x/assets/types" sdk "github.com/cosmos/cosmos-sdk/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" ) var _ assetstype.MsgServer = &Keeper{} @@ -12,6 +14,17 @@ var _ assetstype.MsgServer = &Keeper{} // UpdateParams This function should be triggered by the governance in the future func (k Keeper) UpdateParams(ctx context.Context, params *assetstype.MsgUpdateParams) (*assetstype.MsgUpdateParamsResponse, error) { c := sdk.UnwrapSDKContext(ctx) + if utils.IsMainnet(c.ChainID()) && k.authority != params.Authority { + return nil, govtypes.ErrInvalidSigner.Wrapf( + "invalid authority; expected %s, got %s", + k.authority, params.Authority, + ) + } + c.Logger().Info( + "UpdateParams request", + "authority", k.authority, + "params.AUthority", params.Authority, + ) err := k.SetParams(c, ¶ms.Params) if err != nil { return nil, err diff --git a/x/dogfood/keeper/keeper.go b/x/dogfood/keeper/keeper.go index 861a69b82..7198320fa 100644 --- a/x/dogfood/keeper/keeper.go +++ b/x/dogfood/keeper/keeper.go @@ -40,7 +40,12 @@ type ( ) // NewKeeper creates a new dogfood keeper. -func NewKeeper(cdc codec.BinaryCodec, storeKey storetypes.StoreKey, epochsKeeper types.EpochsKeeper, operatorKeeper types.OperatorKeeper, delegationKeeper keeper.Keeper, restakingKeeper types.AssetsKeeper, avsKeeper types.AVSKeeper, authority string) Keeper { +func NewKeeper( + cdc codec.BinaryCodec, storeKey storetypes.StoreKey, + epochsKeeper types.EpochsKeeper, operatorKeeper types.OperatorKeeper, + delegationKeeper keeper.Keeper, restakingKeeper types.AssetsKeeper, + avsKeeper types.AVSKeeper, authority string, +) Keeper { k := Keeper{ cdc: cdc, storeKey: storeKey, @@ -113,6 +118,10 @@ func (k Keeper) mustValidateFields() { types.PanicIfNil(k.delegationKeeper, "delegationKeeper") types.PanicIfNil(k.restakingKeeper, "restakingKeeper") types.PanicIfNil(k.avsKeeper, "avsKeeper") + // ensure authority is a valid bech32 address + if _, err := sdk.AccAddressFromBech32(k.authority); err != nil { + panic(fmt.Sprintf("authority address %s is invalid: %s", k.authority, err)) + } } // Add the function to get detail information through the operatorKeeper within the dogfood diff --git a/x/dogfood/keeper/msg_server.go b/x/dogfood/keeper/msg_server.go index f4ced9f73..63a810670 100644 --- a/x/dogfood/keeper/msg_server.go +++ b/x/dogfood/keeper/msg_server.go @@ -5,12 +5,13 @@ import ( "strings" "cosmossdk.io/errors" + "github.com/ExocoreNetwork/exocore/utils" avskeeper "github.com/ExocoreNetwork/exocore/x/avs/keeper" avstypes "github.com/ExocoreNetwork/exocore/x/avs/types" - "github.com/ExocoreNetwork/exocore/x/dogfood/types" + epochstypes "github.com/ExocoreNetwork/exocore/x/epochs/types" sdk "github.com/cosmos/cosmos-sdk/types" - epochstypes "github.com/evmos/evmos/v16/x/epochs/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" ) type msgServer struct { @@ -31,13 +32,17 @@ func (k Keeper) UpdateParams( ctx context.Context, msg *types.MsgUpdateParams, ) (*types.MsgUpdateParamsResponse, error) { c := sdk.UnwrapSDKContext(ctx) - // if k.authority != msg.Authority { - // return nil, errorsmod.Wrapf( - // govtypes.ErrInvalidSigner, - // "invalid authority; expected %s, got %s", - // k.authority, msg.Authority, - // ) - // } + if utils.IsMainnet(c.ChainID()) && k.authority != msg.Authority { + return nil, govtypes.ErrInvalidSigner.Wrapf( + "invalid authority; expected %s, got %s", + k.authority, msg.Authority, + ) + } + k.Logger(c).Info( + "UpdateParams request", + "authority", k.authority, + "params.Authority", msg.Authority, + ) prevParams := k.GetDogfoodParams(c) nextParams := msg.Params logger := k.Logger(c) diff --git a/x/exomint/keeper/keeper.go b/x/exomint/keeper/keeper.go index f2172b116..febec52aa 100644 --- a/x/exomint/keeper/keeper.go +++ b/x/exomint/keeper/keeper.go @@ -36,6 +36,10 @@ func NewKeeper( if addr := ak.GetModuleAddress(types.ModuleName); addr == nil { panic(fmt.Sprintf("the x/%s module account has not been set", types.ModuleName)) } + // ensure authority is a valid bech32 address + if _, err := sdk.AccAddressFromBech32(authority); err != nil { + panic(fmt.Sprintf("authority address %s is invalid: %s", authority, err)) + } return Keeper{ cdc: cdc, diff --git a/x/exomint/keeper/msg_server.go b/x/exomint/keeper/msg_server.go index 16a9175e3..daadd4957 100644 --- a/x/exomint/keeper/msg_server.go +++ b/x/exomint/keeper/msg_server.go @@ -4,9 +4,10 @@ import ( "context" errorsmod "cosmossdk.io/errors" - + "github.com/ExocoreNetwork/exocore/utils" "github.com/ExocoreNetwork/exocore/x/exomint/types" sdk "github.com/cosmos/cosmos-sdk/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" ) type msgServer struct { @@ -27,13 +28,17 @@ func (k Keeper) UpdateParams( ctx context.Context, msg *types.MsgUpdateParams, ) (*types.MsgUpdateParamsResponse, error) { c := sdk.UnwrapSDKContext(ctx) - // if k.authority != msg.Authority { - // return nil, errorsmod.Wrapf( - // govtypes.ErrInvalidSigner, - // "invalid authority; expected %s, got %s", - // k.authority, msg.Authority, - // ) - // } + if utils.IsMainnet(c.ChainID()) && k.authority != msg.Authority { + return nil, govtypes.ErrInvalidSigner.Wrapf( + "invalid authority; expected %s, got %s", + k.authority, msg.Authority, + ) + } + k.Logger(c).Info( + "UpdateParams request", + "authority", k.authority, + "params.Authority", msg.Authority, + ) prevParams := k.GetParams(c) nextParams := msg.Params // stateless validations diff --git a/x/feedistribution/keeper/msg_update_params.go b/x/feedistribution/keeper/msg_update_params.go index 08edf1c86..c9c493d92 100644 --- a/x/feedistribution/keeper/msg_update_params.go +++ b/x/feedistribution/keeper/msg_update_params.go @@ -6,20 +6,30 @@ import ( errorsmod "cosmossdk.io/errors" - sdk "github.com/cosmos/cosmos-sdk/types" - + "github.com/ExocoreNetwork/exocore/utils" "github.com/ExocoreNetwork/exocore/x/feedistribution/types" + sdk "github.com/cosmos/cosmos-sdk/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" ) func (k msgServer) UpdateParams(goCtx context.Context, req *types.MsgUpdateParams) (*types.MsgUpdateParamsResponse, error) { - // For test purpose, skip for now - // if k.GetAuthority() != req.Authority { - // return nil, errorsmod.Wrapf(types.ErrInvalidSigner, "invalid authority; expected %s, got %s", k.GetAuthority(), req.Authority) - // } - ctx := sdk.UnwrapSDKContext(goCtx) - epochIdentifier := req.Params.EpochIdentifier + if utils.IsMainnet(ctx.ChainID()) && k.authority != req.Authority { + return nil, govtypes.ErrInvalidSigner.Wrapf( + "invalid authority; expected %s, got %s", + k.authority, req.Authority, + ) + } + + k.Logger().Info( + "UpdateParams request", + "authority", k.authority, + "params.Authority", req.Authority, + ) + + // validate the existence of the epoch (stateful) + epochIdentifier := req.Params.EpochIdentifier _, found := k.epochsKeeper.GetEpochInfo(ctx, epochIdentifier) if !found { return &types.MsgUpdateParamsResponse{}, errorsmod.Wrap(types.ErrEpochNotFound, fmt.Sprintf("epoch info not found %s", epochIdentifier)) diff --git a/x/oracle/keeper/keeper.go b/x/oracle/keeper/keeper.go index c86fe9b04..8ec37b5f9 100644 --- a/x/oracle/keeper/keeper.go +++ b/x/oracle/keeper/keeper.go @@ -21,7 +21,7 @@ type ( storeKey storetypes.StoreKey memKey storetypes.StoreKey paramstore paramtypes.Subspace - // authority string + authority string common.KeeperDogfood delegationKeeper types.DelegationKeeper assetsKeeper types.AssetsKeeper @@ -38,7 +38,12 @@ func NewKeeper( sKeeper common.KeeperDogfood, delegationKeeper types.DelegationKeeper, assetsKeeper types.AssetsKeeper, + authority string, ) Keeper { + // ensure authority is a valid bech32 address + if _, err := sdk.AccAddressFromBech32(authority); err != nil { + panic(fmt.Sprintf("authority address %s is invalid: %s", authority, err)) + } // set KeyTable if it has not already been set if !ps.HasKeyTable() { ps = ps.WithKeyTable(types.ParamKeyTable()) @@ -52,6 +57,7 @@ func NewKeeper( KeeperDogfood: sKeeper, delegationKeeper: delegationKeeper, assetsKeeper: assetsKeeper, + authority: authority, } } diff --git a/x/oracle/keeper/msg_server_update_params.go b/x/oracle/keeper/msg_server_update_params.go index 96f06a23e..400dd7de8 100644 --- a/x/oracle/keeper/msg_server_update_params.go +++ b/x/oracle/keeper/msg_server_update_params.go @@ -3,18 +3,28 @@ package keeper import ( "context" + utils "github.com/ExocoreNetwork/exocore/utils" "github.com/ExocoreNetwork/exocore/x/oracle/keeper/cache" "github.com/ExocoreNetwork/exocore/x/oracle/types" sdk "github.com/cosmos/cosmos-sdk/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" ) func (ms msgServer) UpdateParams(goCtx context.Context, msg *types.MsgUpdateParams) (*types.MsgUpdateParamsResponse, error) { ctx := sdk.UnwrapSDKContext(goCtx) - // TODO: skip the authority check for test - // if ms.authority != msg.Authority { - // return nil, govtypes.ErrInvalidSigner.Wrapf("invalid authority; expected %s, got %s", ms.authority, msg.Authority) - // } + if utils.IsMainnet(ctx.ChainID()) && ms.Keeper.authority != msg.Authority { + return nil, govtypes.ErrInvalidSigner.Wrapf( + "invalid authority; expected %s, got %s", + ms.Keeper.authority, msg.Authority, + ) + } + + ms.Keeper.Logger(ctx).Info( + "UpdateParams request", + "authority", ms.Keeper.authority, + "params.AUthority", msg.Authority, + ) p := ms.GetParams(ctx) var err error diff --git a/x/reward/keeper/claim_reward.go b/x/reward/keeper/claim_reward.go index 97ba0d275..03502443f 100644 --- a/x/reward/keeper/claim_reward.go +++ b/x/reward/keeper/claim_reward.go @@ -3,10 +3,8 @@ package keeper import ( "bytes" "encoding/binary" - "fmt" "log" "math/big" - "strings" errorsmod "cosmossdk.io/errors" sdkmath "cosmossdk.io/math" @@ -14,7 +12,6 @@ import ( rtypes "github.com/ExocoreNetwork/exocore/x/reward/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core" ethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/evmos/evmos/v16/rpc/namespaces/ethereum/eth/filters" @@ -83,13 +80,6 @@ func getRewardParamsFromEventLog(log *ethtypes.Log) (*RewardParams, error) { }, nil } -func getStakeIDAndAssetID(params *RewardParams) (stakeID string, assetID string) { - clientChainLzIDStr := hexutil.EncodeUint64(params.ClientChainLzID) - stakeID = strings.Join([]string{hexutil.Encode(params.WithdrawRewardAddress), clientChainLzIDStr}, "_") - assetID = strings.Join([]string{hexutil.Encode(params.AssetsAddress), clientChainLzIDStr}, "_") - return -} - func (k Keeper) PostTxProcessing(ctx sdk.Context, _ core.Message, receipt *ethtypes.Receipt) error { // TODO check if contract address is valid layerZero relayer address // check if log address and topicId is valid @@ -124,33 +114,38 @@ func (k Keeper) PostTxProcessing(ctx sdk.Context, _ core.Message, receipt *ethty return nil } -func (k Keeper) RewardForWithdraw(ctx sdk.Context, event *RewardParams) error { - // check event parameter then execute RewardForWithdraw operation - if event.OpAmount.IsNegative() { - return errorsmod.Wrap(rtypes.ErrRewardAmountIsNegative, fmt.Sprintf("the amount is:%s", event.OpAmount)) - } - stakeID, assetID := getStakeIDAndAssetID(event) - // check is asset exist - if !k.assetsKeeper.IsStakingAsset(ctx, assetID) { - return errorsmod.Wrap(rtypes.ErrRewardAssetNotExist, fmt.Sprintf("the assetID is:%s", assetID)) - } +func (k Keeper) RewardForWithdraw(sdk.Context, *RewardParams) error { + // TODO: rewards aren't yet supported + // it is safe to return an error, since the precompile call will prevent an error + // if err != nil return false + // the false will ensure no unnecessary LZ messages are sent by the gateway + return rtypes.ErrNotSupportYet + // // check event parameter then execute RewardForWithdraw operation + // if event.OpAmount.IsNegative() { + // return errorsmod.Wrap(rtypes.ErrRewardAmountIsNegative, fmt.Sprintf("the amount is:%s", event.OpAmount)) + // } + // stakeID, assetID := getStakeIDAndAssetID(event) + // // check is asset exist + // if !k.assetsKeeper.IsStakingAsset(ctx, assetID) { + // return errorsmod.Wrap(rtypes.ErrRewardAssetNotExist, fmt.Sprintf("the assetID is:%s", assetID)) + // } - // TODO - changeAmount := types.DeltaStakerSingleAsset{ - TotalDepositAmount: event.OpAmount, - WithdrawableAmount: event.OpAmount, - } - // TODO: there should be a reward pool to be transferred from for native tokens' reward, don't update staker-asset-info, just transfer exo-native-token:pool->staker or handled by validators since the reward would be transferred to validators directly. - if assetID != types.ExocoreAssetID { - err := k.assetsKeeper.UpdateStakerAssetState(ctx, stakeID, assetID, changeAmount) - if err != nil { - return err - } - if err = k.assetsKeeper.UpdateStakingAssetTotalAmount(ctx, assetID, event.OpAmount); err != nil { - return err - } - } - return nil + // // TODO verify the reward amount is valid + // changeAmount := types.DeltaStakerSingleAsset{ + // TotalDepositAmount: event.OpAmount, + // WithdrawableAmount: event.OpAmount, + // } + // // TODO: there should be a reward pool to be transferred from for native tokens' reward, don't update staker-asset-info, just transfer exo-native-token:pool->staker or handled by validators since the reward would be transferred to validators directly. + // if assetID != types.ExocoreAssetID { + // err := k.assetsKeeper.UpdateStakerAssetState(ctx, stakeID, assetID, changeAmount) + // if err != nil { + // return err + // } + // if err = k.assetsKeeper.UpdateStakingAssetTotalAmount(ctx, assetID, event.OpAmount); err != nil { + // return err + // } + // } + // return nil } // WithdrawDelegationRewards is an implementation of a function in the distribution interface. diff --git a/x/reward/keeper/claim_reward_test.go b/x/reward/keeper/claim_reward_test.go index a566e3412..04b7a9098 100644 --- a/x/reward/keeper/claim_reward_test.go +++ b/x/reward/keeper/claim_reward_test.go @@ -9,7 +9,7 @@ import ( ) func (suite *RewardTestSuite) TestClaimWithdrawRequest() { - assets, err := suite.App.AssetsKeeper.GetAllStakingAssetsInfo(suite.Ctx) + _, err := suite.App.AssetsKeeper.GetAllStakingAssetsInfo(suite.Ctx) suite.NoError(err) usdtAddress := common.HexToAddress("0xdAC17F958D2ee523a2206206994597C13D831ec7") @@ -24,24 +24,26 @@ func (suite *RewardTestSuite) TestClaimWithdrawRequest() { // test the case that the deposit asset hasn't registered event.AssetsAddress = usdcAddress[:] err = suite.App.RewardKeeper.RewardForWithdraw(suite.Ctx, event) - suite.ErrorContains(err, rewardtype.ErrRewardAssetNotExist.Error()) + // suite.ErrorContains(err, rewardtype.ErrRewardAssetNotExist.Error()) + suite.ErrorContains(err, rewardtype.ErrNotSupportYet.Error()) // test the normal case event.AssetsAddress = usdtAddress[:] err = suite.App.RewardKeeper.RewardForWithdraw(suite.Ctx, event) - suite.NoError(err) + // suite.NoError(err) + suite.ErrorContains(err, rewardtype.ErrNotSupportYet.Error()) // check state after reward - stakerID, assetID := types.GetStakerIDAndAssetID(event.ClientChainLzID, event.WithdrawRewardAddress, event.AssetsAddress) - info, err := suite.App.AssetsKeeper.GetStakerSpecifiedAssetInfo(suite.Ctx, stakerID, assetID) - suite.NoError(err) - suite.Equal(types.StakerAssetInfo{ - TotalDepositAmount: sdkmath.NewInt(10), - WithdrawableAmount: sdkmath.NewInt(10), - PendingUndelegationAmount: sdkmath.NewInt(0), - }, *info) + // stakerID, assetID := types.GetStakerIDAndAssetID(event.ClientChainLzID, event.WithdrawRewardAddress, event.AssetsAddress) + // info, err := suite.App.AssetsKeeper.GetStakerSpecifiedAssetInfo(suite.Ctx, stakerID, assetID) + // suite.NoError(err) + // suite.Equal(types.StakerAssetInfo{ + // TotalDepositAmount: sdkmath.NewInt(10), + // WithdrawableAmount: sdkmath.NewInt(10), + // PendingUndelegationAmount: sdkmath.NewInt(0), + // }, *info) - assetInfo, err := suite.App.AssetsKeeper.GetStakingAssetInfo(suite.Ctx, assetID) - suite.NoError(err) - suite.Equal(sdkmath.NewInt(10).Add(assets[0].StakingTotalAmount), assetInfo.StakingTotalAmount) + // assetInfo, err := suite.App.AssetsKeeper.GetStakingAssetInfo(suite.Ctx, assetID) + // suite.NoError(err) + // suite.Equal(sdkmath.NewInt(10).Add(assets[0].StakingTotalAmount), assetInfo.StakingTotalAmount) } diff --git a/x/reward/keeper/keeper.go b/x/reward/keeper/keeper.go index b359dc16d..b91985ae4 100644 --- a/x/reward/keeper/keeper.go +++ b/x/reward/keeper/keeper.go @@ -30,6 +30,8 @@ type Keeper struct { banker bankkeeper.Keeper distributor types.Distributor avsKeeper avsKeeper.Keeper + + authority string } func NewKeeper( @@ -37,12 +39,18 @@ func NewKeeper( storeKey storetypes.StoreKey, assetsKeeper assetsKeeper.Keeper, avsKeeper avsKeeper.Keeper, + authority string, ) Keeper { + // ensure authority is a valid bech32 address + if _, err := sdk.AccAddressFromBech32(authority); err != nil { + panic(fmt.Sprintf("authority address %s is invalid: %s", authority, err)) + } return Keeper{ cdc: cdc, storeKey: storeKey, assetsKeeper: assetsKeeper, avsKeeper: avsKeeper, + authority: authority, } } diff --git a/x/reward/keeper/msg_server.go b/x/reward/keeper/msg_server.go index cf86b183a..8f14b58df 100644 --- a/x/reward/keeper/msg_server.go +++ b/x/reward/keeper/msg_server.go @@ -3,8 +3,10 @@ package keeper import ( "context" + "github.com/ExocoreNetwork/exocore/utils" "github.com/ExocoreNetwork/exocore/x/reward/types" sdk "github.com/cosmos/cosmos-sdk/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" ) type msgServer struct { @@ -13,6 +15,19 @@ type msgServer struct { func (k Keeper) UpdateParams(ctx context.Context, params *types.MsgUpdateParams) (*types.MsgUpdateParamsResponse, error) { c := sdk.UnwrapSDKContext(ctx) + if utils.IsMainnet(c.ChainID()) && k.authority != params.Authority { + return nil, govtypes.ErrInvalidSigner.Wrapf( + "invalid authority; expected %s, got %s", + k.authority, params.Authority, + ) + } + + k.Logger(c).Info( + "UpdateParams request", + "authority", k.authority, + "params.AUthority", params.Authority, + ) + err := k.SetParams(c, ¶ms.Params) if err != nil { return nil, err diff --git a/x/slash/keeper/keeper.go b/x/slash/keeper/keeper.go index b4c167223..78b37dd96 100644 --- a/x/slash/keeper/keeper.go +++ b/x/slash/keeper/keeper.go @@ -21,17 +21,25 @@ type Keeper struct { // other keepers assetsKeeper keeper.Keeper + + authority string } func NewKeeper( cdc codec.BinaryCodec, storeKey storetypes.StoreKey, assetsKeeper keeper.Keeper, + authority string, ) Keeper { + // ensure authority is a valid bech32 address + if _, err := sdk.AccAddressFromBech32(authority); err != nil { + panic(fmt.Sprintf("authority address %s is invalid: %s", authority, err)) + } return Keeper{ cdc: cdc, storeKey: storeKey, assetsKeeper: assetsKeeper, + authority: authority, } } diff --git a/x/slash/keeper/msg_server.go b/x/slash/keeper/msg_server.go index d334d6086..9eb4c862a 100644 --- a/x/slash/keeper/msg_server.go +++ b/x/slash/keeper/msg_server.go @@ -3,17 +3,27 @@ package keeper import ( "context" + "github.com/ExocoreNetwork/exocore/utils" "github.com/ExocoreNetwork/exocore/x/slash/types" sdk "github.com/cosmos/cosmos-sdk/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" ) -// nolint: unused // Implementation of the msgServer (via proto) to be done. -type msgServer struct { - Keeper -} - func (k Keeper) UpdateParams(ctx context.Context, params *types.MsgUpdateParams) (*types.MsgUpdateParamsResponse, error) { c := sdk.UnwrapSDKContext(ctx) + if utils.IsMainnet(c.ChainID()) && k.authority != params.Authority { + return nil, govtypes.ErrInvalidSigner.Wrapf( + "invalid authority; expected %s, got %s", + k.authority, params.Authority, + ) + } + + k.Logger(c).Info( + "UpdateParams request", + "authority", k.authority, + "params.AUthority", params.Authority, + ) + err := k.SetParams(c, ¶ms.Params) if err != nil { return nil, err