-
Notifications
You must be signed in to change notification settings - Fork 6
/
feegrant.go
136 lines (119 loc) · 5.55 KB
/
feegrant.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
package keeper
import (
"cosmossdk.io/errors"
"cosmossdk.io/math"
"github.com/chain4energy/c4e-chain/x/cfeclaim/types"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
feegranttypes "github.com/cosmos/cosmos-sdk/x/feegrant"
feegrantkeeper "github.com/cosmos/cosmos-sdk/x/feegrant/keeper"
"strconv"
)
func CreateFeegrantAccountAddress(campaignId uint64) (string, sdk.AccAddress) {
moduleAddressName := types.ModuleName + "-fee-grant-" + strconv.FormatUint(campaignId, 10)
return moduleAddressName, authtypes.NewModuleAddress(moduleAddressName)
}
func calculateFeegrantFeesSum(feegrantAmount math.Int, claimRecordEntriesNumber int64, feegrantDenom string) sdk.Coins {
if feegrantAmount.IsPositive() {
return sdk.NewCoins(sdk.NewCoin(feegrantDenom, feegrantAmount.MulRaw(claimRecordEntriesNumber)))
}
return nil
}
func (k Keeper) setupAndSendFeegrant(ctx sdk.Context, ownerAcc sdk.AccAddress, campaign *types.Campaign, feegrantFeesSum sdk.Coins, claimRecordEntries []*types.ClaimRecordEntry, feegrantDenom string) error {
if campaign.FeegrantAmount.IsPositive() {
acc := k.SetupNewFeegrantAccount(ctx, campaign.Id)
if err := k.bankKeeper.SendCoins(ctx, ownerAcc, acc, feegrantFeesSum); err != nil {
return err
}
if err := k.grantFeeAllowanceToAllClaimRecords(ctx, acc, claimRecordEntries, sdk.NewCoins(sdk.NewCoin(feegrantDenom, campaign.FeegrantAmount))); err != nil {
return err
}
k.Logger(ctx).Debug("setup and send feegrant", "feegrantFeesSum", feegrantFeesSum, "feegrantDenom",
feegrantDenom, "feegrantAmount", campaign.FeegrantAmount, "claimRecordEntriesNumber", len(claimRecordEntries))
}
return nil
}
func (k Keeper) grantFeeAllowanceToAllClaimRecords(ctx sdk.Context, moduleAddress sdk.AccAddress, claimRecordEntries []*types.ClaimRecordEntry, grantAmount sdk.Coins) error {
basicAllowance, err := codectypes.NewAnyWithValue(&feegranttypes.BasicAllowance{
SpendLimit: grantAmount,
})
if err != nil {
return err
}
allowedMsgAllowance := feegranttypes.AllowedMsgAllowance{
Allowance: basicAllowance,
AllowedMessages: []string{sdk.MsgTypeURL(&types.MsgInitialClaim{})},
}
for _, claimRecord := range claimRecordEntries {
granteeAddress, _ := sdk.AccAddressFromBech32(claimRecord.UserEntryAddress)
existingFeeAllowance, _ := k.feeGrantKeeper.GetAllowance(ctx, moduleAddress, granteeAddress)
if existingFeeAllowance == nil {
if err = k.feeGrantKeeper.GrantAllowance(ctx, moduleAddress, granteeAddress, &allowedMsgAllowance); err != nil {
return err
}
}
}
return nil
}
func (k Keeper) sendCampaignFeegrantToOwner(ctx sdk.Context, campaign *types.Campaign) error {
if !campaign.FeegrantAmount.IsPositive() {
return nil
}
_, feegrantAccountAddress := CreateFeegrantAccountAddress(campaign.Id)
feegrantTotalAmount := k.bankKeeper.GetAllBalances(ctx, feegrantAccountAddress)
ownerAddress, _ := sdk.AccAddressFromBech32(campaign.Owner)
k.Logger(ctx).Debug("send campaign feegrant amount to owner", "campaignId", campaign.Id, "owner", campaign.Owner, "amount", feegrantTotalAmount)
return k.bankKeeper.SendCoins(ctx, feegrantAccountAddress, ownerAddress, feegrantTotalAmount)
}
func (k Keeper) deleteClaimRecordSendFeegrant(ctx sdk.Context, campaign *types.Campaign, userEntryAddress string) error {
if !campaign.FeegrantAmount.IsPositive() {
return nil
}
feegrantAccountAddress, granteeAddress, amountLeft, err := k.getFeegrantLeftAmount(ctx, campaign.Id, userEntryAddress)
if err != nil {
return err
}
k.revokeFeeAllowance(ctx, feegrantAccountAddress, granteeAddress)
campaignOwnerAccAddress, err := sdk.AccAddressFromBech32(campaign.Owner)
if err != nil {
return err
}
k.Logger(ctx).Debug("delete claim record send feegrant", "campaignId", campaign.Id, "userEntryAddress", userEntryAddress,
"amountLeft", amountLeft, "feegrantAccountAddress", feegrantAccountAddress, "campaignOwnerAccAddress", campaignOwnerAccAddress)
return k.bankKeeper.SendCoins(ctx, feegrantAccountAddress, campaignOwnerAccAddress, amountLeft)
}
func (k Keeper) getFeegrantLeftAmount(ctx sdk.Context, campaignId uint64, userEntryAddress string) (sdk.AccAddress, sdk.AccAddress, sdk.Coins, error) {
_, granterAddress := CreateFeegrantAccountAddress(campaignId)
granteeAddress, _ := sdk.AccAddressFromBech32(userEntryAddress)
allowance, err := k.feeGrantKeeper.GetAllowance(ctx, granterAddress, granteeAddress)
if err != nil {
return nil, nil, nil, err
}
x, ok := allowance.(*feegranttypes.AllowedMsgAllowance)
if !ok {
return nil, nil, nil, errors.Wrap(sdkerrors.ErrInvalidType, "cannot get AllowedMsgAllowance")
}
for _, msg := range x.AllowedMessages {
if msg == sdk.MsgTypeURL(&types.MsgInitialClaim{}) {
basicAllowance := x.Allowance.GetCachedValue().(*feegranttypes.BasicAllowance)
return granterAddress, granteeAddress, basicAllowance.SpendLimit, nil
}
}
return granterAddress, granteeAddress, nil, errors.Wrap(sdkerrors.ErrInvalidType, "cannot get feegrant left amount")
}
func (k Keeper) revokeFeeAllowance(ctx sdk.Context, granter sdk.Address, grantee sdk.AccAddress) error {
keeper, _ := (k.feeGrantKeeper).(feegrantkeeper.Keeper)
feegrantMsgServer := feegrantkeeper.NewMsgServerImpl(keeper)
msg := feegranttypes.MsgRevokeAllowance{
Granter: granter.String(),
Grantee: grantee.String(),
}
_, err := feegrantMsgServer.RevokeAllowance(sdk.WrapSDKContext(ctx), &msg)
if err != nil {
return err
}
k.Logger(ctx).Debug("revoked fee alowance", "granter", granter, "grantee", grantee)
return nil
}