mirror of
https://github.com/0glabs/0g-chain.git
synced 2024-12-26 00:05:18 +00:00
feat(x/precisebank): Emit events for send/mint/burn (#1955)
Emits the **total** akava amount for both ukava and akava send/mint/burns. If both akava,ukava are sent (not possible via x/evm nor cosmos messages but still an edge case), then the sum is emitted. No other denoms are emitted by x/precisebank as they will be emitted by the underlying x/bank
This commit is contained in:
parent
2d07988994
commit
60a8073574
@ -8,6 +8,7 @@ import (
|
|||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||||
|
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||||
"github.com/kava-labs/kava/x/precisebank/types"
|
"github.com/kava-labs/kava/x/precisebank/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -52,12 +53,23 @@ func (k Keeper) BurnCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) err
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// No more processing required if no ExtendedCoinDenom
|
// Only burn extended coin if the amount is positive
|
||||||
if extendedAmount.IsZero() {
|
if extendedAmount.IsPositive() {
|
||||||
|
if err := k.burnExtendedCoin(ctx, moduleName, extendedAmount); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fullEmissionCoin := types.SumExtendedCoin(amt)
|
||||||
|
if fullEmissionCoin.IsZero() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return k.burnExtendedCoin(ctx, moduleName, extendedAmount)
|
ctx.EventManager().EmitEvent(
|
||||||
|
banktypes.NewCoinBurnEvent(acc.GetAddress(), sdk.NewCoins(fullEmissionCoin)),
|
||||||
|
)
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// burnExtendedCoin burns the fractional amount of the ExtendedCoinDenom from the module account.
|
// burnExtendedCoin burns the fractional amount of the ExtendedCoinDenom from the module account.
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
sdkmath "cosmossdk.io/math"
|
sdkmath "cosmossdk.io/math"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||||
|
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||||
ibctransfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types"
|
ibctransfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types"
|
||||||
"github.com/kava-labs/kava/x/precisebank/keeper"
|
"github.com/kava-labs/kava/x/precisebank/keeper"
|
||||||
"github.com/kava-labs/kava/x/precisebank/testutil"
|
"github.com/kava-labs/kava/x/precisebank/testutil"
|
||||||
@ -209,6 +210,28 @@ func (suite *burnIntegrationTestSuite) TestBurnCoins() {
|
|||||||
res, stop := allInvariantsFn(suite.Ctx)
|
res, stop := allInvariantsFn(suite.Ctx)
|
||||||
suite.Require().False(stop, "invariant should not be broken")
|
suite.Require().False(stop, "invariant should not be broken")
|
||||||
suite.Require().Empty(res, "unexpected invariant message: %s", res)
|
suite.Require().Empty(res, "unexpected invariant message: %s", res)
|
||||||
|
|
||||||
|
intCoinAmt := tt.burnCoins.AmountOf(types.IntegerCoinDenom).
|
||||||
|
Mul(types.ConversionFactor())
|
||||||
|
|
||||||
|
fraCoinAmt := tt.burnCoins.AmountOf(types.ExtendedCoinDenom)
|
||||||
|
|
||||||
|
totalExtCoinAmt := intCoinAmt.Add(fraCoinAmt)
|
||||||
|
|
||||||
|
events := suite.Ctx.EventManager().Events()
|
||||||
|
extendedEvent := banktypes.NewCoinBurnEvent(
|
||||||
|
recipientAddr,
|
||||||
|
sdk.NewCoins(sdk.NewCoin(
|
||||||
|
types.ExtendedCoinDenom,
|
||||||
|
totalExtCoinAmt,
|
||||||
|
)),
|
||||||
|
)
|
||||||
|
|
||||||
|
if totalExtCoinAmt.IsZero() {
|
||||||
|
suite.Require().NotContains(events, extendedEvent)
|
||||||
|
} else {
|
||||||
|
suite.Require().Contains(events, extendedEvent)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||||
|
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||||
|
|
||||||
"github.com/kava-labs/kava/x/precisebank/types"
|
"github.com/kava-labs/kava/x/precisebank/types"
|
||||||
)
|
)
|
||||||
@ -55,12 +56,23 @@ func (k Keeper) MintCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) err
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// No more processing required if no ExtendedCoinDenom
|
// Only mint extended coin if the amount is positive
|
||||||
if extendedAmount.IsZero() {
|
if extendedAmount.IsPositive() {
|
||||||
|
if err := k.mintExtendedCoin(ctx, moduleName, extendedAmount); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fullEmissionCoin := types.SumExtendedCoin(amt)
|
||||||
|
if fullEmissionCoin.IsZero() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return k.mintExtendedCoin(ctx, moduleName, extendedAmount)
|
ctx.EventManager().EmitEvent(
|
||||||
|
banktypes.NewCoinMintEvent(acc.GetAddress(), sdk.NewCoins(fullEmissionCoin)),
|
||||||
|
)
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// mintExtendedCoin manages the minting of only extended coins. This also
|
// mintExtendedCoin manages the minting of only extended coins. This also
|
||||||
|
@ -334,6 +334,30 @@ func (suite *mintIntegrationTestSuite) TestMintCoins() {
|
|||||||
allInvariantsFn := keeper.AllInvariants(suite.Keeper)
|
allInvariantsFn := keeper.AllInvariants(suite.Keeper)
|
||||||
msg, stop := allInvariantsFn(suite.Ctx)
|
msg, stop := allInvariantsFn(suite.Ctx)
|
||||||
suite.Require().Falsef(stop, "invariant should not be broken: %s", msg)
|
suite.Require().Falsef(stop, "invariant should not be broken: %s", msg)
|
||||||
|
|
||||||
|
// Get event for minted coins
|
||||||
|
intCoinAmt := mt.mintAmount.AmountOf(types.IntegerCoinDenom).
|
||||||
|
Mul(types.ConversionFactor())
|
||||||
|
|
||||||
|
fraCoinAmt := mt.mintAmount.AmountOf(types.ExtendedCoinDenom)
|
||||||
|
|
||||||
|
totalExtCoinAmt := intCoinAmt.Add(fraCoinAmt)
|
||||||
|
|
||||||
|
// Check for mint event
|
||||||
|
events := suite.Ctx.EventManager().Events()
|
||||||
|
extendedEvent := banktypes.NewCoinMintEvent(
|
||||||
|
recipientAddr,
|
||||||
|
sdk.NewCoins(sdk.NewCoin(
|
||||||
|
types.ExtendedCoinDenom,
|
||||||
|
totalExtCoinAmt,
|
||||||
|
)),
|
||||||
|
)
|
||||||
|
|
||||||
|
if totalExtCoinAmt.IsZero() {
|
||||||
|
suite.Require().NotContains(events, extendedEvent)
|
||||||
|
} else {
|
||||||
|
suite.Require().Contains(events, extendedEvent)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -8,15 +8,18 @@ import (
|
|||||||
sdkmath "cosmossdk.io/math"
|
sdkmath "cosmossdk.io/math"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||||
|
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||||
"github.com/kava-labs/kava/x/precisebank/types"
|
"github.com/kava-labs/kava/x/precisebank/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
// IsSendEnabledCoins uses the parent x/bank keeper to check the coins provided
|
// IsSendEnabledCoins uses the parent x/bank keeper to check the coins provided
|
||||||
// and returns an ErrSendDisabled if any of the coins are not configured for
|
// and returns an ErrSendDisabled if any of the coins are not configured for
|
||||||
// sending. Returns nil if sending is enabled for all provided coin
|
// sending. Returns nil if sending is enabled for all provided coin.
|
||||||
|
// Note: This method is not used directly by x/evm, but is still required as
|
||||||
|
// part of authtypes.BankKeeper. x/evm uses auth methods that require this
|
||||||
|
// interface.
|
||||||
func (k Keeper) IsSendEnabledCoins(ctx sdk.Context, coins ...sdk.Coin) error {
|
func (k Keeper) IsSendEnabledCoins(ctx sdk.Context, coins ...sdk.Coin) error {
|
||||||
// TODO: This does not actually seem to be used by x/evm, so it should be
|
// Simply pass through to x/bank
|
||||||
// removed from the expected_interface in x/evm.
|
|
||||||
return k.bk.IsSendEnabledCoins(ctx, coins...)
|
return k.bk.IsSendEnabledCoins(ctx, coins...)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,13 +55,35 @@ func (k Keeper) SendCoins(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there is no extended coin amount, we are done
|
// Send the extended coin amount through x/precisebank
|
||||||
if extendedCoinAmount.IsZero() {
|
if extendedCoinAmount.IsPositive() {
|
||||||
|
if err := k.sendExtendedCoins(ctx, from, to, extendedCoinAmount); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get a full extended coin amount (passthrough integer + fractional) ONLY
|
||||||
|
// for event attributes.
|
||||||
|
fullEmissionCoin := types.SumExtendedCoin(amt)
|
||||||
|
|
||||||
|
// If no passthrough integer nor fractional coins, then no event emission.
|
||||||
|
// We also want to emit the event with the whole equivalent extended coin
|
||||||
|
// if only integer coins are sent.
|
||||||
|
if fullEmissionCoin.IsZero() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send the extended coin amount through x/precisebank
|
// Emit transfer event of extended denom for the FULL equivalent value.
|
||||||
return k.sendExtendedCoins(ctx, from, to, extendedCoinAmount)
|
ctx.EventManager().EmitEvents(sdk.Events{
|
||||||
|
sdk.NewEvent(
|
||||||
|
banktypes.EventTypeTransfer,
|
||||||
|
sdk.NewAttribute(banktypes.AttributeKeyRecipient, to.String()),
|
||||||
|
sdk.NewAttribute(banktypes.AttributeKeySender, from.String()),
|
||||||
|
sdk.NewAttribute(sdk.AttributeKeyAmount, fullEmissionCoin.String()),
|
||||||
|
),
|
||||||
|
})
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// sendExtendedCoins transfers amt extended coins from a sending account to a
|
// sendExtendedCoins transfers amt extended coins from a sending account to a
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||||
minttypes "github.com/cosmos/cosmos-sdk/x/mint/types"
|
minttypes "github.com/cosmos/cosmos-sdk/x/mint/types"
|
||||||
"github.com/kava-labs/kava/app"
|
"github.com/kava-labs/kava/app"
|
||||||
"github.com/kava-labs/kava/x/precisebank/keeper"
|
"github.com/kava-labs/kava/x/precisebank/keeper"
|
||||||
@ -400,25 +401,25 @@ func (suite *sendIntegrationTestSuite) TestSendCoins() {
|
|||||||
// Convert send amount coins to extended coins. i.e. if send coins
|
// Convert send amount coins to extended coins. i.e. if send coins
|
||||||
// includes ukava, convert it so that its the equivalent akava
|
// includes ukava, convert it so that its the equivalent akava
|
||||||
// amount so its easier to compare. Compare extended coins only.
|
// amount so its easier to compare. Compare extended coins only.
|
||||||
sendAmountExtended := tt.giveAmt
|
sendAmountFullExtended := tt.giveAmt
|
||||||
sendAmountInteger := tt.giveAmt.AmountOf(types.IntegerCoinDenom)
|
sendAmountInteger := tt.giveAmt.AmountOf(types.IntegerCoinDenom)
|
||||||
if !sendAmountInteger.IsZero() {
|
if !sendAmountInteger.IsZero() {
|
||||||
integerCoin := sdk.NewCoin(types.IntegerCoinDenom, sendAmountInteger)
|
integerCoin := sdk.NewCoin(types.IntegerCoinDenom, sendAmountInteger)
|
||||||
sendAmountExtended = sendAmountExtended.Sub(integerCoin)
|
sendAmountFullExtended = sendAmountFullExtended.Sub(integerCoin)
|
||||||
|
|
||||||
// Add equivalent extended coin
|
// Add equivalent extended coin
|
||||||
extendedCoinAmount := sendAmountInteger.Mul(types.ConversionFactor())
|
extendedCoinAmount := sendAmountInteger.Mul(types.ConversionFactor())
|
||||||
extendedCoin := sdk.NewCoin(types.ExtendedCoinDenom, extendedCoinAmount)
|
extendedCoin := sdk.NewCoin(types.ExtendedCoinDenom, extendedCoinAmount)
|
||||||
sendAmountExtended = sendAmountExtended.Add(extendedCoin)
|
sendAmountFullExtended = sendAmountFullExtended.Add(extendedCoin)
|
||||||
}
|
}
|
||||||
|
|
||||||
suite.Require().Equal(
|
suite.Require().Equal(
|
||||||
senderBalBefore.Sub(sendAmountExtended...),
|
senderBalBefore.Sub(sendAmountFullExtended...),
|
||||||
senderBalAfter,
|
senderBalAfter,
|
||||||
)
|
)
|
||||||
|
|
||||||
suite.Require().Equal(
|
suite.Require().Equal(
|
||||||
recipientBalBefore.Add(sendAmountExtended...),
|
recipientBalBefore.Add(sendAmountFullExtended...),
|
||||||
recipientBalAfter,
|
recipientBalAfter,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -426,6 +427,28 @@ func (suite *sendIntegrationTestSuite) TestSendCoins() {
|
|||||||
res, stop := invariantFn(suite.Ctx)
|
res, stop := invariantFn(suite.Ctx)
|
||||||
suite.Require().False(stop, "invariants should not stop")
|
suite.Require().False(stop, "invariants should not stop")
|
||||||
suite.Require().Empty(res, "invariants should not return any messages")
|
suite.Require().Empty(res, "invariants should not return any messages")
|
||||||
|
|
||||||
|
// Check events
|
||||||
|
|
||||||
|
// FULL akava equivalent, including ukava only/mixed sends
|
||||||
|
sendExtendedAmount := sdk.NewCoin(
|
||||||
|
types.ExtendedCoinDenom,
|
||||||
|
sendAmountFullExtended.AmountOf(types.ExtendedCoinDenom),
|
||||||
|
)
|
||||||
|
|
||||||
|
// No extra events if not sending akava
|
||||||
|
if sendExtendedAmount.IsZero() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
extendedEvent := sdk.NewEvent(
|
||||||
|
banktypes.EventTypeTransfer,
|
||||||
|
sdk.NewAttribute(banktypes.AttributeKeyRecipient, recipient.String()),
|
||||||
|
sdk.NewAttribute(banktypes.AttributeKeySender, sender.String()),
|
||||||
|
sdk.NewAttribute(sdk.AttributeKeyAmount, sendExtendedAmount.String()),
|
||||||
|
)
|
||||||
|
|
||||||
|
suite.Require().Contains(suite.Ctx.EventManager().Events(), extendedEvent)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
25
x/precisebank/types/extended_balance.go
Normal file
25
x/precisebank/types/extended_balance.go
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SumExtendedCoin returns a sdk.Coin of extended coin denomination
|
||||||
|
// with all integer and fractional amounts combined. e.g. if amount contains
|
||||||
|
// both coins of integer denom and extended denom, this will return the total
|
||||||
|
// amount in extended coins. This is intended to get the full value to emit in
|
||||||
|
// events.
|
||||||
|
func SumExtendedCoin(amt sdk.Coins) sdk.Coin {
|
||||||
|
// ukava converted to akava
|
||||||
|
integerAmount := amt.AmountOf(IntegerCoinDenom).Mul(conversionFactor)
|
||||||
|
// akava as is
|
||||||
|
extendedAmount := amt.AmountOf(ExtendedCoinDenom)
|
||||||
|
|
||||||
|
// total of ukava and akava amounts
|
||||||
|
fullEmissionAmount := integerAmount.Add(extendedAmount)
|
||||||
|
|
||||||
|
return sdk.NewCoin(
|
||||||
|
ExtendedCoinDenom,
|
||||||
|
fullEmissionAmount,
|
||||||
|
)
|
||||||
|
}
|
48
x/precisebank/types/extended_balance_test.go
Normal file
48
x/precisebank/types/extended_balance_test.go
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
package types_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
"github.com/kava-labs/kava/x/precisebank/types"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSumExtendedCoin(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
amt sdk.Coins
|
||||||
|
want sdk.Coin
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"empty",
|
||||||
|
sdk.NewCoins(),
|
||||||
|
sdk.NewCoin(types.ExtendedCoinDenom, sdk.ZeroInt()),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"only integer",
|
||||||
|
sdk.NewCoins(sdk.NewInt64Coin(types.IntegerCoinDenom, 100)),
|
||||||
|
sdk.NewCoin(types.ExtendedCoinDenom, types.ConversionFactor().MulRaw(100)),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"only extended",
|
||||||
|
sdk.NewCoins(sdk.NewInt64Coin(types.ExtendedCoinDenom, 100)),
|
||||||
|
sdk.NewCoin(types.ExtendedCoinDenom, sdk.NewInt(100)),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"integer and extended",
|
||||||
|
sdk.NewCoins(
|
||||||
|
sdk.NewInt64Coin(types.IntegerCoinDenom, 100),
|
||||||
|
sdk.NewInt64Coin(types.ExtendedCoinDenom, 100),
|
||||||
|
),
|
||||||
|
sdk.NewCoin(types.ExtendedCoinDenom, types.ConversionFactor().MulRaw(100).AddRaw(100)),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
extVal := types.SumExtendedCoin(tt.amt)
|
||||||
|
require.Equal(t, tt.want, extVal)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user