planetmint-go/x/dao/keeper/msg_server_distribution_result.go
Lorenz Herzberger 8d0e189593
fix: challangee rewards stay in dao module if challenge is not sucessful (#286)
* fix: challangee rewards stay in dao module if challenge is not sucessful

* refactor: split up coin conversion functions

* fix: add dao module coin conversion

* test: adjust test case for updated behavior

* chore: fix typo

* fix: do not mint claims for dao

* refactor: remove redundant statement

* fix: error handling on claim converstion fail

* fix: linter error

* chore: add comment to test case
---------

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>
2024-01-18 13:56:16 +01:00

117 lines
3.6 KiB
Go

package keeper
import (
"context"
"strconv"
errorsmod "cosmossdk.io/errors"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/planetmint/planetmint-go/config"
"github.com/planetmint/planetmint-go/util"
"github.com/planetmint/planetmint-go/x/dao/types"
)
func (k msgServer) DistributionResult(goCtx context.Context, msg *types.MsgDistributionResult) (*types.MsgDistributionResultResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
distribution, found := k.LookupDistributionOrder(ctx, msg.GetLastPop())
if found {
distribution.DaoTxID = msg.DaoTxID
distribution.PopTxID = msg.PopTxID
distribution.InvestorTxID = msg.InvestorTxID
err := k.resolveStagedClaims(ctx, distribution.FirstPop, distribution.LastPop)
if err != nil {
util.GetAppLogger().Error(ctx, "%s for provided PoP heights: %d %d", types.ErrResolvingStagedClaims.Error(), distribution.FirstPop, distribution.LastPop)
return nil, errorsmod.Wrap(types.ErrConvertClaims, err.Error())
}
util.GetAppLogger().Info(ctx, "staged claims successfully for provided PoP heights: %d %d", distribution.FirstPop, distribution.LastPop)
k.StoreDistributionOrder(ctx, distribution)
} else {
util.GetAppLogger().Error(ctx, "%s for provided block height %s", types.ErrDistributionNotFound.Error(), strconv.FormatInt(msg.GetLastPop(), 10))
}
return &types.MsgDistributionResultResponse{}, nil
}
func (k msgServer) resolveStagedClaims(ctx sdk.Context, start int64, end int64) (err error) {
// lookup all challenges since the last distribution
challenges, err := k.GetChallengeRange(ctx, start, end)
if err != nil {
return err
}
popParticipants := make(map[string]uint64)
for _, challenge := range challenges {
// if challenge not finished nobody has claims
if !challenge.GetFinished() {
continue
}
_, challengerAmt, challengeeAmt := util.GetPopReward(challenge.Height)
popParticipants[challenge.Challenger] += challengerAmt
if challenge.GetSuccess() {
popParticipants[challenge.Challengee] += challengeeAmt
}
}
// second data structure because map iteration order is not guaranteed in GO
keys := make([]string, 0)
for p := range popParticipants {
keys = append(keys, p)
}
for _, p := range keys {
err = k.convertAccountClaim(ctx, p, popParticipants[p])
if err != nil {
return err
}
}
return
}
// convert per account
func (k msgServer) convertAccountClaim(ctx sdk.Context, participant string, amount uint64) (err error) {
conf := config.GetConfig()
accAddr, err := sdk.AccAddressFromBech32(participant)
if err != nil {
return err
}
accStagedClaim := k.bankKeeper.GetBalance(ctx, accAddr, conf.StagedDenom)
if accStagedClaim.Amount.GTE(sdk.NewIntFromUint64(amount)) {
burnCoins, mintCoins := getConvertCoins(amount)
err = k.bankKeeper.SendCoinsFromAccountToModule(ctx, accAddr, types.ModuleName, burnCoins)
if err != nil {
return err
}
err = k.convertCoins(ctx, burnCoins, mintCoins)
if err != nil {
return err
}
err = k.bankKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, accAddr, mintCoins)
if err != nil {
return err
}
}
return
}
func (k msgServer) convertCoins(ctx sdk.Context, burnCoins sdk.Coins, mintCoins sdk.Coins) (err error) {
err = k.bankKeeper.BurnCoins(ctx, types.ModuleName, burnCoins)
if err != nil {
return err
}
return k.bankKeeper.MintCoins(ctx, types.ModuleName, mintCoins)
}
func getConvertCoins(amount uint64) (burnCoins sdk.Coins, mintCoins sdk.Coins) {
conf := config.GetConfig()
burnCoins = sdk.NewCoins(sdk.NewCoin(conf.StagedDenom, sdk.NewIntFromUint64(amount)))
mintCoins = sdk.NewCoins(sdk.NewCoin(conf.ClaimDenom, sdk.NewIntFromUint64(amount)))
return
}