-
Notifications
You must be signed in to change notification settings - Fork 411
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Handle wasmvm Burn message #489
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -181,6 +181,7 @@ var ( | |
stakingtypes.NotBondedPoolName: {authtypes.Burner, authtypes.Staking}, | ||
govtypes.ModuleName: {authtypes.Burner}, | ||
ibctransfertypes.ModuleName: {authtypes.Minter, authtypes.Burner}, | ||
wasm.ModuleName: {authtypes.Burner}, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💯 |
||
} | ||
|
||
// module accounts that are allowed to receive tokens | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,14 +24,23 @@ type SDKMessageHandler struct { | |
encoders msgEncoder | ||
} | ||
|
||
func NewDefaultMessageHandler(router sdk.Router, channelKeeper types.ChannelKeeper, capabilityKeeper types.CapabilityKeeper, unpacker codectypes.AnyUnpacker, portSource types.ICS20TransferPortSource, customEncoders ...*MessageEncoders) Messenger { | ||
func NewDefaultMessageHandler( | ||
router sdk.Router, | ||
channelKeeper types.ChannelKeeper, | ||
capabilityKeeper types.CapabilityKeeper, | ||
bankKeeper types.Burner, | ||
unpacker codectypes.AnyUnpacker, | ||
portSource types.ICS20TransferPortSource, | ||
customEncoders ...*MessageEncoders, | ||
) Messenger { | ||
encoders := DefaultEncoders(unpacker, portSource) | ||
for _, e := range customEncoders { | ||
encoders = encoders.Merge(e) | ||
} | ||
return NewMessageHandlerChain( | ||
NewSDKMessageHandler(router, encoders), | ||
NewIBCRawPacketHandler(channelKeeper, capabilityKeeper), | ||
NewBurnCoinMessageHandler(bankKeeper), | ||
) | ||
} | ||
|
||
|
@@ -168,3 +177,33 @@ func (h IBCRawPacketHandler) DispatchMsg(ctx sdk.Context, _ sdk.AccAddress, cont | |
) | ||
return nil, nil, h.channelKeeper.SendPacket(ctx, channelCap, packet) | ||
} | ||
|
||
var _ Messenger = MessageHandlerFunc(nil) | ||
|
||
// MessageHandlerFunc is a helper to construct simple function based message handler | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like it. |
||
type MessageHandlerFunc func(ctx sdk.Context, contractAddr sdk.AccAddress, contractIBCPortID string, msg wasmvmtypes.CosmosMsg) (events []sdk.Event, data [][]byte, err error) | ||
|
||
func (m MessageHandlerFunc) DispatchMsg(ctx sdk.Context, contractAddr sdk.AccAddress, contractIBCPortID string, msg wasmvmtypes.CosmosMsg) (events []sdk.Event, data [][]byte, err error) { | ||
return m(ctx, contractAddr, contractIBCPortID, msg) | ||
} | ||
|
||
// NewBurnCoinMessageHandler handles wasmvm.BurnMsg messages | ||
func NewBurnCoinMessageHandler(burner types.Burner) MessageHandlerFunc { | ||
return func(ctx sdk.Context, contractAddr sdk.AccAddress, _ string, msg wasmvmtypes.CosmosMsg) (events []sdk.Event, data [][]byte, err error) { | ||
if msg.Bank != nil && msg.Bank.Burn != nil { | ||
coins, err := convertWasmCoinsToSdkCoins(msg.Bank.Burn.Amount) | ||
if err != nil { | ||
return nil, nil, err | ||
} | ||
if err := burner.SendCoinsFromAccountToModule(ctx, contractAddr, types.ModuleName, coins); err != nil { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, it is a two step process? Only module accounts can burn. Glad you took this on and not me. So many gotchas |
||
return nil, nil, sdkerrors.Wrap(err, "transfer to module") | ||
} | ||
if err := burner.BurnCoins(ctx, types.ModuleName, coins); err != nil { | ||
return nil, nil, sdkerrors.Wrap(err, "burn coins") | ||
} | ||
moduleLogger(ctx).Info("Burned", "amount", coins) | ||
return nil, nil, nil | ||
} | ||
return nil, nil, types.ErrUnknownMsg | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,10 +4,12 @@ import ( | |
"encoding/json" | ||
"github.com/CosmWasm/wasmd/x/wasm/keeper/wasmtesting" | ||
"github.com/CosmWasm/wasmd/x/wasm/types" | ||
wasmvm "github.com/CosmWasm/wasmvm" | ||
wasmvmtypes "github.com/CosmWasm/wasmvm/types" | ||
"github.com/cosmos/cosmos-sdk/baseapp" | ||
sdk "github.com/cosmos/cosmos-sdk/types" | ||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" | ||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" | ||
capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" | ||
clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" | ||
channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" | ||
|
@@ -306,3 +308,87 @@ func TestIBCRawPacketHandler(t *testing.T) { | |
}) | ||
} | ||
} | ||
|
||
func TestBurnCoinMessageHandlerIntegration(t *testing.T) { | ||
// testing via full keeper setup so that we are confident the | ||
// module permissions are set correct and no other handler | ||
// picks the message in the default handler chain | ||
ctx, keepers := CreateDefaultTestInput(t) | ||
k := keepers.WasmKeeper | ||
|
||
before, err := keepers.BankKeeper.TotalSupply(sdk.WrapSDKContext(ctx), &banktypes.QueryTotalSupplyRequest{}) | ||
require.NoError(t, err) | ||
example := InstantiateHackatomExampleContract(t, ctx, keepers) // with deposit of 100 stake | ||
|
||
specs := map[string]struct { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
msg wasmvmtypes.BurnMsg | ||
expErr bool | ||
}{ | ||
"all good": { | ||
msg: wasmvmtypes.BurnMsg{ | ||
Amount: wasmvmtypes.Coins{{ | ||
Denom: "denom", | ||
Amount: "100", | ||
}}, | ||
}, | ||
}, | ||
"not enough funds in contract": { | ||
msg: wasmvmtypes.BurnMsg{ | ||
Amount: wasmvmtypes.Coins{{ | ||
Denom: "denom", | ||
Amount: "101", | ||
}}, | ||
}, | ||
expErr: true, | ||
}, | ||
"zero amount rejected": { | ||
msg: wasmvmtypes.BurnMsg{ | ||
Amount: wasmvmtypes.Coins{{ | ||
Denom: "denom", | ||
Amount: "0", | ||
}}, | ||
}, | ||
expErr: true, | ||
}, | ||
"unknown denom - insufficient funds": { | ||
msg: wasmvmtypes.BurnMsg{ | ||
Amount: wasmvmtypes.Coins{{ | ||
Denom: "unknown", | ||
Amount: "1", | ||
}}, | ||
}, | ||
expErr: true, | ||
}, | ||
} | ||
parentCtx := ctx | ||
for name, spec := range specs { | ||
t.Run(name, func(t *testing.T) { | ||
ctx, _ = parentCtx.CacheContext() | ||
k.wasmVM = &wasmtesting.MockWasmer{ExecuteFn: func(codeID wasmvm.Checksum, env wasmvmtypes.Env, info wasmvmtypes.MessageInfo, executeMsg []byte, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.Response, uint64, error) { | ||
return &wasmvmtypes.Response{Messages: []wasmvmtypes.CosmosMsg{ | ||
{Bank: &wasmvmtypes.BankMsg{Burn: &spec.msg}}, | ||
}, | ||
}, 0, nil | ||
}} | ||
|
||
// when | ||
_, err = k.execute(ctx, example.Contract, example.CreatorAddr, nil, nil) | ||
|
||
// then | ||
if spec.expErr { | ||
require.Error(t, err) | ||
return | ||
} | ||
require.NoError(t, err) | ||
|
||
// and total supply reduced by burned amount | ||
after, err := keepers.BankKeeper.TotalSupply(sdk.WrapSDKContext(ctx), &banktypes.QueryTotalSupplyRequest{}) | ||
require.NoError(t, err) | ||
diff := before.Supply.Sub(after.Supply) | ||
assert.Equal(t, sdk.NewCoins(sdk.NewCoin("denom", sdk.NewInt(100))), diff) | ||
}) | ||
} | ||
|
||
// test cases: | ||
// not enough money to burn | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, you fixed this. Thank you