forked from neutron-org/neutron
-
Notifications
You must be signed in to change notification settings - Fork 0
/
keeper.go
144 lines (120 loc) · 4.67 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
144
package keeper
import (
"fmt"
"cosmossdk.io/errors"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/cometbft/cometbft/libs/log"
"github.com/cosmos/cosmos-sdk/codec"
storetypes "github.com/cosmos/cosmos-sdk/store/types"
sdk "github.com/cosmos/cosmos-sdk/types"
consumertypes "github.com/cosmos/interchain-security/v3/x/ccv/consumer/types"
"github.com/MonikaCat/neutron/v2/x/feeburner/types"
)
type (
Keeper struct {
cdc codec.BinaryCodec
storeKey storetypes.StoreKey
memKey storetypes.StoreKey
accountKeeper types.AccountKeeper
bankKeeper types.BankKeeper
authority string
}
)
var KeyBurnedFees = []byte("BurnedFees")
func NewKeeper(
cdc codec.BinaryCodec,
storeKey,
memKey storetypes.StoreKey,
accountKeeper types.AccountKeeper,
bankKeeper types.BankKeeper,
authority string,
) *Keeper {
return &Keeper{
cdc: cdc,
storeKey: storeKey,
memKey: memKey,
accountKeeper: accountKeeper,
bankKeeper: bankKeeper,
authority: authority,
}
}
func (k Keeper) GetAuthority() string {
return k.authority
}
// RecordBurnedFees adds `amount` to the total amount of burned NTRN tokens
func (k Keeper) RecordBurnedFees(ctx sdk.Context, amount sdk.Coin) {
store := ctx.KVStore(k.storeKey)
totalBurnedNeutronsAmount := k.GetTotalBurnedNeutronsAmount(ctx)
totalBurnedNeutronsAmount.Coin = totalBurnedNeutronsAmount.Coin.Add(amount)
store.Set(KeyBurnedFees, k.cdc.MustMarshal(&totalBurnedNeutronsAmount))
}
// GetTotalBurnedNeutronsAmount gets the total burned amount of NTRN tokens
func (k Keeper) GetTotalBurnedNeutronsAmount(ctx sdk.Context) types.TotalBurnedNeutronsAmount {
store := ctx.KVStore(k.storeKey)
var totalBurnedNeutronsAmount types.TotalBurnedNeutronsAmount
bzTotalBurnedNeutronsAmount := store.Get(KeyBurnedFees)
if bzTotalBurnedNeutronsAmount != nil {
k.cdc.MustUnmarshal(bzTotalBurnedNeutronsAmount, &totalBurnedNeutronsAmount)
}
if totalBurnedNeutronsAmount.Coin.Denom == "" {
totalBurnedNeutronsAmount.Coin = sdk.NewCoin(k.GetParams(ctx).NeutronDenom, sdk.NewInt(0))
}
return totalBurnedNeutronsAmount
}
// BurnAndDistribute is an important part of tokenomics. It does few things:
// 1. Burns NTRN fee coins distributed to consumertypes.ConsumerRedistributeName in ICS (https://github.com/cosmos/interchain-security/v3/blob/v0.2.0/x/ccv/consumer/keeper/distribution.go#L17)
// 2. Updates total amount of burned NTRN coins
// 3. Sends non-NTRN fee tokens to reserve contract address
// Panics if no `consumertypes.ConsumerRedistributeName` module found OR could not burn NTRN tokens
func (k Keeper) BurnAndDistribute(ctx sdk.Context) {
moduleAddr := k.accountKeeper.GetModuleAddress(consumertypes.ConsumerRedistributeName)
if moduleAddr == nil {
panic("ConsumerRedistributeName must have module address")
}
params := k.GetParams(ctx)
balances := k.bankKeeper.GetAllBalances(ctx, moduleAddr)
fundsForReserve := make(sdk.Coins, 0, len(balances))
for _, balance := range balances {
if !balance.IsZero() {
if balance.Denom == params.NeutronDenom {
err := k.bankKeeper.BurnCoins(ctx, consumertypes.ConsumerRedistributeName, sdk.Coins{balance})
if err != nil {
panic(errors.Wrapf(err, "failed to burn NTRN tokens during fee processing"))
}
k.RecordBurnedFees(ctx, balance)
} else {
fundsForReserve = append(fundsForReserve, balance)
}
}
}
if len(fundsForReserve) > 0 {
addr, err := sdk.AccAddressFromBech32(params.TreasuryAddress)
if err != nil {
// there's no way we face this kind of situation in production, since it means the chain is misconfigured
// still, in test environments it might be the case when the chain is started without Reserve
// in such case we just burn the tokens
err := k.bankKeeper.BurnCoins(ctx, consumertypes.ConsumerRedistributeName, fundsForReserve)
if err != nil {
panic(errors.Wrapf(err, "failed to burn tokens during fee processing"))
}
} else {
err = k.bankKeeper.SendCoins(
ctx,
moduleAddr, addr,
fundsForReserve,
)
if err != nil {
panic(errors.Wrapf(err, "failed sending funds to Reserve"))
}
}
}
}
func (k Keeper) Logger(ctx sdk.Context) log.Logger {
return ctx.Logger().With("module", fmt.Sprintf("x/%s", types.ModuleName))
}
// FundCommunityPool is method to satisfy DistributionKeeper interface for packet-forward-middleware Keeper.
// The original method sends coins to a community pool of a chain.
// The current method sends coins to a Fee Collector module which collects fee on consumer chain.
func (k Keeper) FundCommunityPool(ctx sdk.Context, amount sdk.Coins, sender sdk.AccAddress) error {
return k.bankKeeper.SendCoinsFromAccountToModule(ctx, sender, authtypes.FeeCollectorName, amount)
}