-
Notifications
You must be signed in to change notification settings - Fork 0
/
keeper.go
146 lines (122 loc) · 4.8 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
145
146
package keeper
import (
"fmt"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/cosmos/cosmos-sdk/codec"
storetypes "github.com/cosmos/cosmos-sdk/store/types"
sdk "github.com/cosmos/cosmos-sdk/types"
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
consumertypes "github.com/cosmos/interchain-security/x/ccv/consumer/types"
"github.com/tendermint/tendermint/libs/log"
"github.com/merlin-network/petri/x/feeburner/types"
)
type (
Keeper struct {
cdc codec.BinaryCodec
storeKey storetypes.StoreKey
memKey storetypes.StoreKey
paramstore paramtypes.Subspace
accountKeeper types.AccountKeeper
bankKeeper types.BankKeeper
}
)
var KeyBurnedFees = []byte("BurnedFees")
func NewKeeper(
cdc codec.BinaryCodec,
storeKey,
memKey storetypes.StoreKey,
ps paramtypes.Subspace,
accountKeeper types.AccountKeeper,
bankKeeper types.BankKeeper,
) *Keeper {
// set KeyTable if it has not already been set
if !ps.HasKeyTable() {
ps = ps.WithKeyTable(types.ParamKeyTable())
}
return &Keeper{
cdc: cdc,
storeKey: storeKey,
memKey: memKey,
paramstore: ps,
accountKeeper: accountKeeper,
bankKeeper: bankKeeper,
}
}
// RecordBurnedFees adds `amount` to the total amount of burned FURY tokens
func (k Keeper) RecordBurnedFees(ctx sdk.Context, amount sdk.Coin) {
store := ctx.KVStore(k.storeKey)
totalBurnedPetrisAmount := k.GetTotalBurnedPetrisAmount(ctx)
totalBurnedPetrisAmount.Coin = totalBurnedPetrisAmount.Coin.Add(amount)
store.Set(KeyBurnedFees, k.cdc.MustMarshal(&totalBurnedPetrisAmount))
}
// GetTotalBurnedPetrisAmount gets the total burned amount of FURY tokens
func (k Keeper) GetTotalBurnedPetrisAmount(ctx sdk.Context) types.TotalBurnedPetrisAmount {
store := ctx.KVStore(k.storeKey)
var totalBurnedPetrisAmount types.TotalBurnedPetrisAmount
bzTotalBurnedPetrisAmount := store.Get(KeyBurnedFees)
if bzTotalBurnedPetrisAmount != nil {
k.cdc.MustUnmarshal(bzTotalBurnedPetrisAmount, &totalBurnedPetrisAmount)
}
if totalBurnedPetrisAmount.Coin.Denom == "" {
totalBurnedPetrisAmount.Coin = sdk.NewCoin(k.GetParams(ctx).PetriDenom, sdk.NewInt(0))
}
return totalBurnedPetrisAmount
}
// BurnAndDistribute is an important part of tokenomics. It does few things:
// 1. Burns FURY fee coins distributed to consumertypes.ConsumerRedistributeName in ICS (https://github.com/cosmos/interchain-security/blob/v0.2.0/x/ccv/consumer/keeper/distribution.go#L17)
// 2. Updates total amount of burned FURY coins
// 3. Sends non-FURY fee tokens to reserve contract address
// Panics if no `consumertypes.ConsumerRedistributeName` module found OR could not burn FURY 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.PetriDenom {
err := k.bankKeeper.BurnCoins(ctx, consumertypes.ConsumerRedistributeName, sdk.Coins{balance})
if err != nil {
panic(sdkerrors.Wrapf(err, "failed to burn FURY 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(sdkerrors.Wrapf(err, "failed to burn tokens during fee processing"))
}
} else {
err = k.bankKeeper.SendCoins(
ctx,
moduleAddr, addr,
fundsForReserve,
)
if err != nil {
panic(sdkerrors.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)
}