> ## Documentation Index
> Fetch the complete documentation index at: https://cosmos-docs-sync-security-docs.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Keepers

<Note>
  **Synopsis**
  `Keeper`s refer to a Cosmos SDK abstraction whose role is to manage access to the subset of the state defined by various modules. `Keeper`s are module-specific, i.e. the subset of state defined by a module can only be accessed by a `keeper` defined in said module. If a module needs to access the subset of state defined by another module, a reference to the second module's internal `keeper` needs to be passed to the first one. This is done in `app.go` during the instantiation of module keepers.
</Note>

<Note>
  **Pre-requisite Readings**

  * [Introduction to Cosmos SDK Modules](/sdk/v0.50/build/building-modules/intro)
</Note>

## Motivation

The Cosmos SDK is a framework that makes it easy for developers to build complex decentralized applications from scratch, mainly by composing modules together. As the ecosystem of open-source modules for the Cosmos SDK expands, it will become increasingly likely that some of these modules contain vulnerabilities, as a result of the negligence or malice of their developer.

The Cosmos SDK adopts an [object-capabilities-based approach](/sdk/v0.50/learn/advanced/ocap) to help developers better protect their application from unwanted inter-module interactions, and `keeper`s are at the core of this approach. A `keeper` can be considered quite literally to be the gatekeeper of a module's store(s). Each store (typically an [`IAVL` Store](/sdk/v0.50/learn/advanced/store#iavl-store)) defined within a module comes with a `storeKey`, which grants unlimited access to it. The module's `keeper` holds this `storeKey` (which should otherwise remain unexposed), and defines [methods](#implementing-methods) for reading and writing to the store(s).

The core idea behind the object-capabilities approach is to only reveal what is necessary to get the work done. In practice, this means that instead of handling permissions of modules through access-control lists, module `keeper`s are passed a reference to the specific instance of the other modules' `keeper`s that they need to access (this is done in the [application's constructor function](/sdk/v0.50/learn/beginner/app-anatomy#constructor-function)). As a consequence, a module can only interact with the subset of state defined in another module via the methods exposed by the instance of the other module's `keeper`. This is a great way for developers to control the interactions that their own module can have with modules developed by external developers.

## Type Definition

`keeper`s are generally implemented in a `/keeper/keeper.go` file located in the module's folder. By convention, the type `keeper` of a module is simply named `Keeper` and usually follows the following structure:

```go theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
type Keeper struct {
    // External keepers, if any

    // Store key(s)

    // codec

    // authority
}
```

For example, here is the type definition of the `keeper` from the `staking` module:

```go expandable theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
package keeper

import (
    
	"fmt"
    "cosmossdk.io/log"
    "cosmossdk.io/math"
	abci "github.com/cometbft/cometbft/abci/types"

	storetypes "cosmossdk.io/store/types"
    "github.com/cosmos/cosmos-sdk/codec"
	sdk "github.com/cosmos/cosmos-sdk/types"
    "github.com/cosmos/cosmos-sdk/x/staking/types"
)

// Implements ValidatorSet interface
var _ types.ValidatorSet = Keeper{
}

// Implements DelegationSet interface
var _ types.DelegationSet = Keeper{
}

// Keeper of the x/staking store
type Keeper struct {
    storeKey   storetypes.StoreKey
	cdc        codec.BinaryCodec
	authKeeper types.AccountKeeper
	bankKeeper types.BankKeeper
	hooks      types.StakingHooks
	authority  string
}

// NewKeeper creates a new staking Keeper instance
func NewKeeper(
	cdc codec.BinaryCodec,
	key storetypes.StoreKey,
	ak types.AccountKeeper,
	bk types.BankKeeper,
	authority string,
) *Keeper {
	// ensure bonded and not bonded module accounts are set
    if addr := ak.GetModuleAddress(types.BondedPoolName); addr == nil {
    panic(fmt.Sprintf("%s module account has not been set", types.BondedPoolName))
}
    if addr := ak.GetModuleAddress(types.NotBondedPoolName); addr == nil {
    panic(fmt.Sprintf("%s module account has not been set", types.NotBondedPoolName))
}

	// ensure that authority is a valid AccAddress
    if _, err := ak.AddressCodec().StringToBytes(authority); err != nil {
    panic("authority is not a valid acc address")
}

return &Keeper{
    storeKey:   key,
		cdc:        cdc,
		authKeeper: ak,
		bankKeeper: bk,
		hooks:      nil,
		authority:  authority,
}
}

// Logger returns a module-specific logger.
func (k Keeper)

Logger(ctx sdk.Context)

log.Logger {
    return ctx.Logger().With("module", "x/"+types.ModuleName)
}

// Hooks gets the hooks for staking *Keeper {
    func (k *Keeper)

Hooks()

types.StakingHooks {
    if k.hooks == nil {
		// return a no-op implementation if no hooks are set
		return types.MultiStakingHooks{
}
	
}

return k.hooks
}

// SetHooks Set the validator hooks.  In contrast to other receivers, this method must take a pointer due to nature
// of the hooks interface and SDK start up sequence.
func (k *Keeper)

SetHooks(sh types.StakingHooks) {
    if k.hooks != nil {
    panic("cannot set validator hooks twice")
}

k.hooks = sh
}

// GetLastTotalPower Load the last total validator power.
func (k Keeper)

GetLastTotalPower(ctx sdk.Context)

math.Int {
    store := ctx.KVStore(k.storeKey)
    bz := store.Get(types.LastTotalPowerKey)
    if bz == nil {
    return math.ZeroInt()
}
    ip := sdk.IntProto{
}

k.cdc.MustUnmarshal(bz, &ip)

return ip.Int
}

// SetLastTotalPower Set the last total validator power.
func (k Keeper)

SetLastTotalPower(ctx sdk.Context, power math.Int) {
    store := ctx.KVStore(k.storeKey)
    bz := k.cdc.MustMarshal(&sdk.IntProto{
    Int: power
})

store.Set(types.LastTotalPowerKey, bz)
}

// GetAuthority returns the x/staking module's authority.
func (k Keeper)

GetAuthority()

string {
    return k.authority
}

// SetValidatorUpdates sets the ABCI validator power updates for the current block.
func (k Keeper)

SetValidatorUpdates(ctx sdk.Context, valUpdates []abci.ValidatorUpdate) {
    store := ctx.KVStore(k.storeKey)
    bz := k.cdc.MustMarshal(&types.ValidatorUpdates{
    Updates: valUpdates
})

store.Set(types.ValidatorUpdatesKey, bz)
}

// GetValidatorUpdates returns the ABCI validator power updates within the current block.
func (k Keeper)

GetValidatorUpdates(ctx sdk.Context) []abci.ValidatorUpdate {
    store := ctx.KVStore(k.storeKey)
    bz := store.Get(types.ValidatorUpdatesKey)

var valUpdates types.ValidatorUpdates
	k.cdc.MustUnmarshal(bz, &valUpdates)

return valUpdates.Updates
}
```

Let us go through the different parameters:

* An expected `keeper` is a `keeper` external to a module that is required by the internal `keeper` of said module. External `keeper`s are listed in the internal `keeper`'s type definition as interfaces. These interfaces are themselves defined in an `expected_keepers.go` file in the root of the module's folder. In this context, interfaces are used to reduce the number of dependencies, as well as to facilitate the maintenance of the module itself.
* `storeKey`s grant access to the store(s) of the [multistore](/sdk/v0.50/learn/advanced/store) managed by the module. They should always remain unexposed to external modules.
* `cdc` is the [codec](/sdk/v0.50/learn/advanced/encoding) used to marshall and unmarshall structs to/from `[]byte`. The `cdc` can be any of `codec.BinaryCodec`, `codec.JSONCodec` or `codec.Codec` based on your requirements. It can be either a proto or amino codec as long as they implement these interfaces.
* The authority listed is a module account or user account that has the right to change module level parameters. Previously this was handled by the param module, which has been deprecated.

Of course, it is possible to define different types of internal `keeper`s for the same module (e.g. a read-only `keeper`). Each type of `keeper` comes with its own constructor function, which is called from the [application's constructor function](/sdk/v0.50/learn/beginner/app-anatomy). This is where `keeper`s are instantiated, and where developers make sure to pass correct instances of modules' `keeper`s to other modules that require them.

## Implementing Methods

`Keeper`s primarily expose getter and setter methods for the store(s) managed by their module. These methods should remain as simple as possible and strictly be limited to getting or setting the requested value, as validity checks should have already been performed by the [`Msg` server](/sdk/v0.50/build/building-modules/msg-services) when `keeper`s' methods are called.

Typically, a *getter* method will have the following signature

```go theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
func (k Keeper)

Get(ctx context.Context, key string)

returnType
```

and the method will go through the following steps:

1. Retrieve the appropriate store from the `ctx` using the `storeKey`. This is done through the `KVStore(storeKey sdk.StoreKey)` method of the `ctx`. Then it's preferred to use the `prefix.Store` to access only the desired limited subset of the store for convenience and safety.
2. If it exists, get the `[]byte` value stored at location `[]byte(key)` using the `Get(key []byte)` method of the store.
3. Unmarshall the retrieved value from `[]byte` to `returnType` using the codec `cdc`. Return the value.

Similarly, a *setter* method will have the following signature

```go theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
func (k Keeper)

Set(ctx context.Context, key string, value valueType)
```

and the method will go through the following steps:

1. Retrieve the appropriate store from the `ctx` using the `storeKey`. This is done through the `KVStore(storeKey sdk.StoreKey)` method of the `ctx`. It's preferred to use the `prefix.Store` to access only the desired limited subset of the store for convenience and safety.
2. Marshal `value` to `[]byte` using the codec `cdc`.
3. Set the encoded value in the store at location `key` using the `Set(key []byte, value []byte)` method of the store.

For more, see an example of `keeper`'s [methods implementation from the `staking` module](https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/x/staking/keeper/keeper.go).

The [module `KVStore`](/sdk/v0.50/learn/advanced/store#kvstore-and-commitkvstore-interfaces) also provides an `Iterator()` method which returns an `Iterator` object to iterate over a domain of keys.

This is an example from the `auth` module to iterate accounts:

```go expandable theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
package keeper

import (
    
	"context"
    "errors"
    "cosmossdk.io/collections"

	sdk "github.com/cosmos/cosmos-sdk/types"
)

// NewAccountWithAddress implements AccountKeeperI.
func (ak AccountKeeper)

NewAccountWithAddress(ctx context.Context, addr sdk.AccAddress)

sdk.AccountI {
    acc := ak.proto()
    err := acc.SetAddress(addr)
    if err != nil {
    panic(err)
}

return ak.NewAccount(ctx, acc)
}

// NewAccount sets the next account number to a given account interface
func (ak AccountKeeper)

NewAccount(ctx context.Context, acc sdk.AccountI)

sdk.AccountI {
    if err := acc.SetAccountNumber(ak.NextAccountNumber(ctx)); err != nil {
    panic(err)
}

return acc
}

// HasAccount implements AccountKeeperI.
func (ak AccountKeeper)

HasAccount(ctx context.Context, addr sdk.AccAddress)

bool {
    has, _ := ak.Accounts.Has(ctx, addr)

return has
}

// GetAccount implements AccountKeeperI.
func (ak AccountKeeper)

GetAccount(ctx context.Context, addr sdk.AccAddress)

sdk.AccountI {
    acc, err := ak.Accounts.Get(ctx, addr)
    if err != nil && !errors.Is(err, collections.ErrNotFound) {
    panic(err)
}

return acc
}

// GetAllAccounts returns all accounts in the accountKeeper.
func (ak AccountKeeper)

GetAllAccounts(ctx context.Context) (accounts []sdk.AccountI) {
    ak.IterateAccounts(ctx, func(acc sdk.AccountI) (stop bool) {
    accounts = append(accounts, acc)

return false
})

return accounts
}

// SetAccount implements AccountKeeperI.
func (ak AccountKeeper)

SetAccount(ctx context.Context, acc sdk.AccountI) {
    err := ak.Accounts.Set(ctx, acc.GetAddress(), acc)
    if err != nil {
    panic(err)
}
}

// RemoveAccount removes an account for the account mapper store.
// NOTE: this will cause supply invariant violation if called
func (ak AccountKeeper)

RemoveAccount(ctx context.Context, acc sdk.AccountI) {
    err := ak.Accounts.Remove(ctx, acc.GetAddress())
    if err != nil {
    panic(err)
}
}

// IterateAccounts iterates over all the stored accounts and performs a callback function.
// Stops iteration when callback returns true.
func (ak AccountKeeper)

IterateAccounts(ctx context.Context, cb func(account sdk.AccountI) (stop bool)) {
    err := ak.Accounts.Walk(ctx, nil, func(_ sdk.AccAddress, value sdk.AccountI) (bool, error) {
    return cb(value), nil
})
    if err != nil {
    panic(err)
}
}
```
