-
Notifications
You must be signed in to change notification settings - Fork 8
/
keeper.go
143 lines (113 loc) · 4.32 KB
/
keeper.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
package keeper
import (
"bytes"
"fmt"
"github.com/tendermint/tendermint/libs/log"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
paramstypes "github.com/cosmos/cosmos-sdk/x/params/types"
"github.com/bianjieai/iritamod/modules/opb/types"
)
// Keeper defines the OPB keeper
type Keeper struct {
cdc codec.Codec
storeKey sdk.StoreKey
accountKeeper types.AccountKeeper
bankKeeper types.BankKeeper
tokenKeeper types.TokenKeeper
permKeeper types.PermKeeper
paramSpace paramstypes.Subspace
}
// NewKeeper creates a new Keeper instance
func NewKeeper(
cdc codec.Codec,
storeKey sdk.StoreKey,
accountKeeper types.AccountKeeper,
bankKeeper types.BankKeeper,
tokenKeeper types.TokenKeeper,
permKeeper types.PermKeeper,
paramSpace paramstypes.Subspace,
) Keeper {
// ensure the OPB module account is set
if addr := accountKeeper.GetModuleAddress(types.PointTokenFeeCollectorName); addr == nil {
panic(fmt.Sprintf("%s module account has not been set", types.PointTokenFeeCollectorName))
}
if !paramSpace.HasKeyTable() {
paramSpace = paramSpace.WithKeyTable(ParamKeyTable())
}
return Keeper{
cdc: cdc,
storeKey: storeKey,
accountKeeper: accountKeeper,
bankKeeper: bankKeeper,
tokenKeeper: tokenKeeper,
permKeeper: permKeeper,
paramSpace: paramSpace,
}
}
// Logger returns a module-specific logger.
func (k Keeper) Logger(ctx sdk.Context) log.Logger {
return ctx.Logger().With("module", fmt.Sprintf("iritamod/%s", types.ModuleName))
}
// Mint mints the base native token by the specified amount
// NOTE: the operator must possess the BaseM1Admin or RootAdmin permission
func (k Keeper) Mint(ctx sdk.Context, amount uint64, recipient, operator sdk.AccAddress) error {
// get the base token denom
baseTokenDenom := k.BaseTokenDenom(ctx)
if !k.hasBaseM1Perm(ctx, operator) {
return sdkerrors.Wrapf(types.ErrUnauthorized, "address %s has no permission to mint %s", operator, baseTokenDenom)
}
// get the base token
baseToken, err := k.tokenKeeper.GetToken(ctx, baseTokenDenom)
if err != nil {
return sdkerrors.Wrapf(types.ErrInvalidDenom, "token for %s does not exist", baseTokenDenom)
}
// NOTE: empty owner
owner := sdk.AccAddress{}
return k.tokenKeeper.MintToken(ctx, baseToken.GetSymbol(), amount, recipient, owner)
}
// Reclaim reclaims the native token of the specified denom from the corresponding escrow account
// NOTE: the operator must possess the certain permission
func (k Keeper) Reclaim(ctx sdk.Context, denom string, recipient, operator sdk.AccAddress) error {
baseTokenDenom := k.BaseTokenDenom(ctx)
pointTokenDenom := k.PointTokenDenom(ctx)
var moduleAccName string
switch denom {
case baseTokenDenom, "ugas":
if !k.hasBaseM1Perm(ctx, operator) {
return sdkerrors.Wrapf(types.ErrUnauthorized, "address %s has no permission to reclaim %s", operator, denom)
}
moduleAccName = authtypes.FeeCollectorName
case pointTokenDenom:
owner, err := k.tokenKeeper.GetOwner(ctx, denom)
if err != nil {
return sdkerrors.Wrapf(types.ErrInvalidDenom, "token for %s does not exist", denom)
}
if !bytes.Equal(operator, owner) {
return sdkerrors.Wrapf(types.ErrUnauthorized, "only %s is allowed to reclaim %s", owner, denom)
}
moduleAccName = types.PointTokenFeeCollectorName
default:
return sdkerrors.Wrapf(types.ErrInvalidDenom, "denom must be either %s or %s", baseTokenDenom, pointTokenDenom)
}
moduleAccAddr := k.accountKeeper.GetModuleAddress(moduleAccName)
balance := k.bankKeeper.GetBalance(ctx, moduleAccAddr, denom)
if balance.IsZero() {
return sdkerrors.Wrapf(sdkerrors.ErrInsufficientFunds, "no balance for %s in the module account", denom)
}
return k.bankKeeper.SendCoinsFromModuleToAccount(ctx, moduleAccName, recipient, sdk.NewCoins(balance))
}
// HasToken checks if the given token exists
func (k Keeper) HasToken(ctx sdk.Context, denom string) bool {
if _, err := k.tokenKeeper.GetToken(ctx, denom); err != nil {
return false
}
return true
}
// hasBaseM1Perm returns true if the given address is BaseM1Admin or RootAdmin
// False otherwise
func (k Keeper) hasBaseM1Perm(ctx sdk.Context, address sdk.AccAddress) bool {
return k.permKeeper.IsRootAdmin(ctx, address) || k.permKeeper.IsBaseM1Admin(ctx, address)
}