Skip to content

Commit

Permalink
Mint rewards initial impl
Browse files Browse the repository at this point in the history
  • Loading branch information
maurolacy committed Oct 31, 2024
1 parent 8dfeaea commit 31421e1
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 6 deletions.
44 changes: 38 additions & 6 deletions x/babylon/keeper/handler_plugin.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package keeper

import (
sdkmath "cosmossdk.io/math"
"encoding/json"

wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper"
wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types"
wasmvmtypes "github.com/CosmWasm/wasmvm/v2/types"
Expand All @@ -22,10 +22,13 @@ type AuthSource interface {
}

// abstract keeper
type msKeeper interface{}
type babylonKeeper interface {
GetParams(ctx sdk.Context) types.Params
MintBlockRewards(ctx sdk.Context, recipient sdk.AccAddress, amount sdk.Coin) (sdkmath.Int, error)
}

type CustomMsgHandler struct {
k msKeeper
k babylonKeeper
auth AuthSource
}

Expand All @@ -36,7 +39,7 @@ func NewDefaultCustomMsgHandler(k *Keeper) *CustomMsgHandler {

// NewCustomMsgHandler constructor to set up CustomMsgHandler with an individual auth source.
// This is an extension point for non default contract authorization logic.
func NewCustomMsgHandler(k msKeeper, auth AuthSource) *CustomMsgHandler {
func NewCustomMsgHandler(k babylonKeeper, auth AuthSource) *CustomMsgHandler {
return &CustomMsgHandler{k: k, auth: auth}
}

Expand Down Expand Up @@ -67,8 +70,37 @@ func (h CustomMsgHandler) DispatchMsg(ctx sdk.Context, contractAddr sdk.AccAddre
return h.handleMintRewardsMsg(ctx, contractAddr, customMsg.MintRewards)
}

func (h CustomMsgHandler) handleMintRewardsMsg(ctx sdk.Context, actor sdk.AccAddress, mintRewardsMsg *contract.MintRewardsMsg) ([]sdk.Event, [][]byte, [][]*codectypes.Any, error) {
return []sdk.Event{}, nil, nil, nil
func (h CustomMsgHandler) handleMintRewardsMsg(ctx sdk.Context, actor sdk.AccAddress, mintMsg *contract.MintRewardsMsg) ([]sdk.Event, [][]byte, [][]*codectypes.Any, error) {
coin, err := wasmkeeper.ConvertWasmCoinToSdkCoin(mintMsg.Amount)
if err != nil {
return nil, nil, nil, err
}
params := h.k.GetParams(ctx)
// Validate actor
if actor.String() != params.BtcFinalityContractAddress {
return nil, nil, nil, sdkerrors.ErrUnauthorized.Wrapf("minter must be the finality contract")
}

// Define recipient
recipient, err := sdk.AccAddressFromBech32(mintMsg.Recipient)
if err != nil {
return nil, nil, nil, err
}
if err != nil {
return nil, nil, nil, err
}

rewards, err := h.k.MintBlockRewards(ctx, recipient, coin)
if err != nil {
return nil, nil, nil, err
}

return []sdk.Event{sdk.NewEvent(
types.EventTypeMintRewards,
sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName),
sdk.NewAttribute(sdk.AttributeKeySender, actor.String()),
sdk.NewAttribute(sdk.AttributeKeyAmount, rewards.String()),
)}, nil, nil, nil
}

// AuthSourceFn is helper for simple AuthSource types
Expand Down
56 changes: 56 additions & 0 deletions x/babylon/keeper/mint_rewards.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package keeper

import (
sdkmath "cosmossdk.io/math"
"github.com/babylonlabs-io/babylon-sdk/x/babylon/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/errors"
)

// MintBlockRewards mints new "virtual" bonding tokens and sends them to the staking contract for distribution.
// The amount minted is removed from the SupplyOffset (so that it will become negative), when supported.
// Authorization of the actor/recipient should be handled before entering this method.
// The amount is computed based on the finality inflation rate and the total staking token supply, in the bonded denom
func (k Keeper) MintBlockRewards(pCtx sdk.Context, recipient sdk.AccAddress, amt sdk.Coin) (sdkmath.Int, error) {
if amt.Amount.IsNil() || amt.Amount.IsZero() || amt.Amount.IsNegative() {
return sdkmath.ZeroInt(), errors.ErrInvalidRequest.Wrap("amount")
}

// Ensure staking constraints
bondDenom, err := k.Staking.BondDenom(pCtx)
if err != nil {
return sdkmath.ZeroInt(), err
}
if amt.Denom != bondDenom {
return sdkmath.ZeroInt(), errors.ErrInvalidRequest.Wrapf("invalid coin denomination: got %s, expected %s", amt.Denom, bondDenom)
}
// FIXME? Remove this constraint for flexibility
params := k.GetParams(pCtx)
if recipient.String() != params.BtcStakingContractAddress {
return sdkmath.ZeroInt(), errors.ErrUnauthorized.Wrapf("invalid recipient: got %s, expected staking contract (%s)",
recipient, params.BtcStakingContractAddress)
}

// TODO?: Ensure Babylon constraints

cacheCtx, done := pCtx.CacheContext() // work in a cached store as Osmosis (safety net?)

// Mint rewards tokens
coins := sdk.NewCoins(amt)
err = k.bank.MintCoins(cacheCtx, types.ModuleName, coins)
if err != nil {
return sdkmath.ZeroInt(), err
}

// FIXME: Confirm we want this supply offset enabled for rewards, i.e.
// as virtual coins that do not count to the total supply
//k.bank.AddSupplyOffset(cacheCtx, bondDenom, amt.Amount.Neg())

err = k.bank.SendCoinsFromModuleToAccount(cacheCtx, types.ModuleName, recipient, coins)
if err != nil {
return sdkmath.ZeroInt(), err
}

done()
return amt.Amount, err
}
1 change: 1 addition & 0 deletions x/babylon/types/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const (
EventTypeMaxCapLimitUpdated = "max_cap_limit_updated"
EventTypeUnbond = "instant_unbond"
EventTypeDelegate = "instant_delegate"
EventTypeMintRewards = "mint_rewards"
)

const (
Expand Down
3 changes: 3 additions & 0 deletions x/babylon/types/expected_keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package types

import (
context "context"
sdkmath "cosmossdk.io/math"

sdk "github.com/cosmos/cosmos-sdk/types"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
Expand All @@ -18,6 +19,8 @@ type BankKeeper interface {

// StakingKeeper expected staking keeper.
type StakingKeeper interface {
BondDenom(ctx context.Context) (string, error)
StakingTokenSupply(ctx context.Context) (sdkmath.Int, error)
}

// AccountKeeper interface contains functions for getting accounts and the module address
Expand Down

0 comments on commit 31421e1

Please sign in to comment.