package keeper import ( "fmt" "github.com/CosmWasm/wasmd/x/wasm/internal/types" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" ) // NewWasmProposalHandler creates a new governance Handler for wasm proposals func NewWasmProposalHandler(k Keeper, enabledProposalTypes []types.ProposalType) govtypes.Handler { enabledTypes := make(map[string]struct{}, len(enabledProposalTypes)) for i := range enabledProposalTypes { enabledTypes[string(enabledProposalTypes[i])] = struct{}{} } return func(ctx sdk.Context, content govtypes.Content) error { if content == nil { return sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "content must not be empty") } if _, ok := enabledTypes[content.ProposalType()]; !ok { return sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unsupported wasm proposal content type: %q", content.ProposalType()) } switch c := content.(type) { case *types.StoreCodeProposal: return handleStoreCodeProposal(ctx, k, *c) case *types.InstantiateContractProposal: return handleInstantiateProposal(ctx, k, *c) case *types.MigrateContractProposal: return handleMigrateProposal(ctx, k, *c) case *types.UpdateAdminProposal: return handleUpdateAdminProposal(ctx, k, *c) case *types.ClearAdminProposal: return handleClearAdminProposal(ctx, k, *c) default: return sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized wasm proposal content type: %T", c) } } } func handleStoreCodeProposal(ctx sdk.Context, k Keeper, p types.StoreCodeProposal) error { if err := p.ValidateBasic(); err != nil { return err } runAsAddr, err := sdk.AccAddressFromBech32(p.RunAs) if err != nil { return sdkerrors.Wrap(err, "run as address") } codeID, err := k.create(ctx, runAsAddr, p.WASMByteCode, p.Source, p.Builder, p.InstantiatePermission, GovAuthorizationPolicy{}) if err != nil { return err } ourEvent := sdk.NewEvent( sdk.EventTypeMessage, sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName), sdk.NewAttribute(types.AttributeKeyCodeID, fmt.Sprintf("%d", codeID)), ) ctx.EventManager().EmitEvent(ourEvent) return nil } func handleInstantiateProposal(ctx sdk.Context, k Keeper, p types.InstantiateContractProposal) error { if err := p.ValidateBasic(); err != nil { return err } runAsAddr, err := sdk.AccAddressFromBech32(p.RunAs) if err != nil { return sdkerrors.Wrap(err, "run as address") } adminAddr, err := sdk.AccAddressFromBech32(p.Admin) if err != nil { return sdkerrors.Wrap(err, "admin") } contractAddr, err := k.instantiate(ctx, p.CodeID, runAsAddr, adminAddr, p.InitMsg, p.Label, p.Funds, GovAuthorizationPolicy{}) if err != nil { return err } ourEvent := sdk.NewEvent( sdk.EventTypeMessage, sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName), sdk.NewAttribute(types.AttributeKeyCodeID, fmt.Sprintf("%d", p.CodeID)), sdk.NewAttribute(types.AttributeKeyContract, contractAddr.String()), ) ctx.EventManager().EmitEvent(ourEvent) return nil } func handleMigrateProposal(ctx sdk.Context, k Keeper, p types.MigrateContractProposal) error { if err := p.ValidateBasic(); err != nil { return err } contractAddr, err := sdk.AccAddressFromBech32(p.Contract) if err != nil { return sdkerrors.Wrap(err, "contract") } runAsAddr, err := sdk.AccAddressFromBech32(p.RunAs) if err != nil { return sdkerrors.Wrap(err, "run as address") } res, err := k.migrate(ctx, contractAddr, runAsAddr, p.CodeID, p.MigrateMsg, GovAuthorizationPolicy{}) if err != nil { return err } ourEvent := sdk.NewEvent( sdk.EventTypeMessage, sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName), sdk.NewAttribute(types.AttributeKeyContract, p.Contract), ) ctx.EventManager().EmitEvent(ourEvent) for _, e := range res.Events { attr := make([]sdk.Attribute, len(e.Attributes)) for i, a := range e.Attributes { attr[i] = sdk.NewAttribute(string(a.Key), string(a.Value)) } ctx.EventManager().EmitEvent(sdk.NewEvent(e.Type, attr...)) } return nil } func handleUpdateAdminProposal(ctx sdk.Context, k Keeper, p types.UpdateAdminProposal) error { if err := p.ValidateBasic(); err != nil { return err } contractAddr, err := sdk.AccAddressFromBech32(p.Contract) if err != nil { return sdkerrors.Wrap(err, "contract") } newAdminAddr, err := sdk.AccAddressFromBech32(p.NewAdmin) if err != nil { return sdkerrors.Wrap(err, "run as address") } if err := k.setContractAdmin(ctx, contractAddr, nil, newAdminAddr, GovAuthorizationPolicy{}); err != nil { return err } ourEvent := sdk.NewEvent( sdk.EventTypeMessage, sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName), sdk.NewAttribute(types.AttributeKeyContract, p.Contract), ) ctx.EventManager().EmitEvent(ourEvent) return nil } func handleClearAdminProposal(ctx sdk.Context, k Keeper, p types.ClearAdminProposal) error { if err := p.ValidateBasic(); err != nil { return err } contractAddr, err := sdk.AccAddressFromBech32(p.Contract) if err != nil { return sdkerrors.Wrap(err, "contract") } if err := k.setContractAdmin(ctx, contractAddr, nil, nil, GovAuthorizationPolicy{}); err != nil { return err } ourEvent := sdk.NewEvent( sdk.EventTypeMessage, sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName), sdk.NewAttribute(types.AttributeKeyContract, p.Contract), ) ctx.EventManager().EmitEvent(ourEvent) return nil }