# State and Keeper
The module `Custom_Asset` keeps state of
- All custom tokens created
- All tokens/addresses that are frozen
### State (types.go)
```go
type FreezeList struct {
map[string][]sdk.AccAddress
}
```
```go
type CustomToken struct {
denom string
minter sdk.AccAddress
supply sdk.Int
}
```
----
````go
type CustomToken struct {
denom string
minter sdk.AccAddress
supply sdk.Int
frozen_addresses []sdk.AccAddress
}
````
- - Optionally we can also maintain the same state using just one struct,but the first implementation provides faster lookups at the cost of slightly higher storage
- Also note I used the type `sdk.AccAddress` to make things clear, it would be better to use strings,because after 0.42 all addresses are treated as strings in the sdk.This is true for all documents .
### Keeper (keeper.go)
- The keeper provides the state transitions and queries for the state
#### State Transitions
```go
func (keeper)CreateCustomToken (ctx sdk.Context,c types.CustomToken){}
func (keeper)AddToFreezeList (ctx sdk.Context,denom string,freezingAddress sdk.AccAddress){}
func (keeper)RemoveFromFreezeList (ctx sdk.Context,denom string,unFreezingAddress sdk.AccAddress){}
```
#### Helpers / Queries
```go
func (keeper)IsFrozen (ctx sdk.Context,denom string,checkingAddress string){
- Convert string to address
- Get freezelist for denom
- Iterate list , if a value matches the checkingAddress return true
- return false after loop
}
func (keeper)IsCustomAsset(ctx sdk.Context,checkingDenom string) bool {
- Get Prefixed iterator
- Iterate all records
- if record.denom == checkingDenom return true
- return false at the end of the loop
}
```
- It would also have queries , but I am not going into those details
The `bank_wrapper` module does not have any state of its own.