Skip to content
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

Add proposal instantiate 2 #1106

Merged
merged 9 commits into from
Dec 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions docs/proto/proto-docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
- [AccessConfigUpdate](#cosmwasm.wasm.v1.AccessConfigUpdate)
- [ClearAdminProposal](#cosmwasm.wasm.v1.ClearAdminProposal)
- [ExecuteContractProposal](#cosmwasm.wasm.v1.ExecuteContractProposal)
- [InstantiateContract2Proposal](#cosmwasm.wasm.v1.InstantiateContract2Proposal)
- [InstantiateContractProposal](#cosmwasm.wasm.v1.InstantiateContractProposal)
- [MigrateContractProposal](#cosmwasm.wasm.v1.MigrateContractProposal)
- [PinCodesProposal](#cosmwasm.wasm.v1.PinCodesProposal)
Expand Down Expand Up @@ -923,6 +924,30 @@ contract.



<a name="cosmwasm.wasm.v1.InstantiateContract2Proposal"></a>

### InstantiateContract2Proposal
InstantiateContract2Proposal gov proposal content type to instantiate contract 2


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `title` | [string](#string) | | Title is a short summary |
| `description` | [string](#string) | | Description is a human readable text |
| `run_as` | [string](#string) | | RunAs is the address that is passed to the contract's enviroment as sender |
| `admin` | [string](#string) | | Admin is an optional address that can execute migrations |
| `code_id` | [uint64](#uint64) | | CodeID is the reference to the stored WASM code |
| `label` | [string](#string) | | Label is optional metadata to be stored with a constract instance. |
| `msg` | [bytes](#bytes) | | Msg json encode message to be passed to the contract on instantiation |
| `funds` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | Funds coins that are transferred to the contract on instantiation |
| `salt` | [bytes](#bytes) | | Salt is an arbitrary value provided by the sender. Size can be 1 to 64. |
| `fix_msg` | [bool](#bool) | | FixMsg include the msg value into the hash for the predictable address. Default is false |






<a name="cosmwasm.wasm.v1.InstantiateContractProposal"></a>

### InstantiateContractProposal
Expand Down
28 changes: 28 additions & 0 deletions proto/cosmwasm/wasm/v1/proposal.proto
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,34 @@ message InstantiateContractProposal {
];
}

// InstantiateContract2Proposal gov proposal content type to instantiate contract 2
message InstantiateContract2Proposal {
// Title is a short summary
string title = 1;
// Description is a human readable text
string description = 2;
// RunAs is the address that is passed to the contract's enviroment as sender
string run_as = 3;
// Admin is an optional address that can execute migrations
string admin = 4;
// CodeID is the reference to the stored WASM code
uint64 code_id = 5 [ (gogoproto.customname) = "CodeID" ];
// Label is optional metadata to be stored with a constract instance.
string label = 6;
// Msg json encode message to be passed to the contract on instantiation
bytes msg = 7 [ (gogoproto.casttype) = "RawContractMessage" ];
// Funds coins that are transferred to the contract on instantiation
repeated cosmos.base.v1beta1.Coin funds = 8 [
(gogoproto.nullable) = false,
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"
];
// Salt is an arbitrary value provided by the sender. Size can be 1 to 64.
bytes salt = 9;
// FixMsg include the msg value into the hash for the predictable address.
// Default is false
bool fix_msg = 10;
}

// MigrateContractProposal gov proposal content type to migrate a contract.
message MigrateContractProposal {
// Title is a short summary
Expand Down
66 changes: 66 additions & 0 deletions x/wasm/client/cli/gov_tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package cli
import (
"bytes"
"crypto/sha256"
"encoding/hex"
"fmt"
"net/url"
"strconv"
Expand Down Expand Up @@ -199,6 +200,71 @@ func ProposalInstantiateContractCmd() *cobra.Command {
return cmd
}

func ProposalInstantiateContract2Cmd() *cobra.Command {
decoder := newArgDecoder(hex.DecodeString)
cmd := &cobra.Command{
Use: "instantiate-contract-2 [code_id_int64] [json_encoded_init_args] [salt] --label [text] --title [text] --description [text] --run-as [address] --admin [address,optional] --amount [coins,optional] --fix-msg [bool,optional]",
Short: "Submit an instantiate wasm contract proposal with predictable address",
Args: cobra.ExactArgs(3),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, proposalTitle, proposalDescr, deposit, err := getProposalInfo(cmd)
if err != nil {
return err
}

src, err := parseInstantiateArgs(args[0], args[1], clientCtx.FromAddress, cmd.Flags())
if err != nil {
return err
}

runAs, err := cmd.Flags().GetString(flagRunAs)
if err != nil {
return fmt.Errorf("run-as: %s", err)
}
if len(runAs) == 0 {
return errors.New("run-as address is required")
}

salt, err := decoder.DecodeString(args[2])
if err != nil {
return fmt.Errorf("salt: %w", err)
}

fixMsg, err := cmd.Flags().GetBool(flagFixMsg)
if err != nil {
return fmt.Errorf("fix msg: %w", err)
}

content := types.NewInstantiateContract2Proposal(proposalTitle, proposalDescr, runAs, src.Admin, src.CodeID, src.Label, src.Msg, src.Funds, salt, fixMsg)

msg, err := govtypes.NewMsgSubmitProposal(content, deposit, clientCtx.GetFromAddress())
if err != nil {
return err
}
if err = msg.ValidateBasic(); err != nil {
return err
}

return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
},
SilenceUsage: true,
}

cmd.Flags().String(flagAmount, "", "Coins to send to the contract during instantiation")
cmd.Flags().String(flagLabel, "", "A human-readable name for this contract in lists")
cmd.Flags().String(flagAdmin, "", "Address of an admin")
cmd.Flags().String(flagRunAs, "", "The address that pays the init funds. It is the creator of the contract and passed to the contract as sender on proposal execution")
cmd.Flags().Bool(flagNoAdmin, false, "You must set this explicitly if you don't want an admin")
cmd.Flags().Bool(flagFixMsg, false, "An optional flag to include the json_encoded_init_args for the predictable address generation mode")
decoder.RegisterFlags(cmd.PersistentFlags(), "salt")

// proposal flags
cmd.Flags().String(cli.FlagTitle, "", "Title of proposal")
cmd.Flags().String(cli.FlagDescription, "", "Description of proposal")
cmd.Flags().String(cli.FlagDeposit, "", "Deposit of proposal")
return cmd
}

func ProposalStoreAndInstantiateContractCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "store-instantiate [wasm file] [json_encoded_init_args] --label [text] --title [text] --description [text] --run-as [address]" +
Expand Down
1 change: 1 addition & 0 deletions x/wasm/client/proposal_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,5 @@ var ProposalHandlers = []govclient.ProposalHandler{
govclient.NewProposalHandler(cli.ProposalUnpinCodesCmd, rest.UnpinCodeProposalHandler),
govclient.NewProposalHandler(cli.ProposalUpdateInstantiateConfigCmd, rest.UpdateInstantiateConfigProposalHandler),
govclient.NewProposalHandler(cli.ProposalStoreAndInstantiateContractCmd, rest.EmptyRestHandler),
govclient.NewProposalHandler(cli.ProposalInstantiateContract2Cmd, rest.EmptyRestHandler),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 easy to miss

}
34 changes: 34 additions & 0 deletions x/wasm/keeper/proposal_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ func NewWasmProposalHandlerX(k types.ContractOpsKeeper, enabledProposalTypes []t
return handleStoreCodeProposal(ctx, k, *c)
case *types.InstantiateContractProposal:
return handleInstantiateProposal(ctx, k, *c)
case *types.InstantiateContract2Proposal:
return handleInstantiate2Proposal(ctx, k, *c)
case *types.MigrateContractProposal:
return handleMigrateProposal(ctx, k, *c)
case *types.SudoContractProposal:
Expand Down Expand Up @@ -111,6 +113,38 @@ func handleInstantiateProposal(ctx sdk.Context, k types.ContractOpsKeeper, p typ
return nil
}

func handleInstantiate2Proposal(ctx sdk.Context, k types.ContractOpsKeeper, p types.InstantiateContract2Proposal) error {
// Validatebasic with proposal
if err := p.ValidateBasic(); err != nil {
return err
}

// Get runAsAddr as AccAddress
runAsAddr, err := sdk.AccAddressFromBech32(p.RunAs)
if err != nil {
return sdkerrors.Wrap(err, "run as address")
}

// Get admin address
var adminAddr sdk.AccAddress
if p.Admin != "" {
if adminAddr, err = sdk.AccAddressFromBech32(p.Admin); err != nil {
return sdkerrors.Wrap(err, "admin")
}
}

_, data, err := k.Instantiate2(ctx, p.CodeID, runAsAddr, adminAddr, p.Msg, p.Label, p.Funds, p.Salt, p.FixMsg)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:thu

if err != nil {
return err
}

ctx.EventManager().EmitEvent(sdk.NewEvent(
types.EventTypeGovContractResult,
sdk.NewAttribute(types.AttributeKeyResultDataHex, hex.EncodeToString(data)),
))
return nil
}

func handleStoreAndInstantiateContractProposal(ctx sdk.Context, k types.ContractOpsKeeper, p types.StoreAndInstantiateContractProposal) error {
if err := p.ValidateBasic(); err != nil {
return err
Expand Down
64 changes: 64 additions & 0 deletions x/wasm/keeper/proposal_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,70 @@ func TestInstantiateProposal(t *testing.T) {
require.NotEmpty(t, em.Events()[2].Attributes[0])
}

func TestInstantiate2Proposal(t *testing.T) {
ctx, keepers := CreateTestInput(t, false, "staking")
govKeeper, wasmKeeper := keepers.GovKeeper, keepers.WasmKeeper
wasmKeeper.SetParams(ctx, types.Params{
CodeUploadAccess: types.AllowNobody,
InstantiateDefaultPermission: types.AccessTypeNobody,
})

wasmCode, err := os.ReadFile("./testdata/hackatom.wasm")
require.NoError(t, err)

codeInfo := types.CodeInfoFixture(types.WithSHA256CodeHash(wasmCode))
err = wasmKeeper.importCode(ctx, 1, codeInfo, wasmCode)
require.NoError(t, err)

var (
oneAddress sdk.AccAddress = bytes.Repeat([]byte{0x1}, types.ContractAddrLen)
otherAddress sdk.AccAddress = bytes.Repeat([]byte{0x2}, types.ContractAddrLen)
label string = "label"
salt []byte = []byte("mySalt")
)
src := types.InstantiateContract2ProposalFixture(func(p *types.InstantiateContract2Proposal) {
p.CodeID = firstCodeID
p.RunAs = oneAddress.String()
p.Admin = otherAddress.String()
p.Label = label
p.Salt = salt
})
contractAddress := BuildContractAddressPredictable(codeInfo.CodeHash, oneAddress, salt, []byte{})

em := sdk.NewEventManager()

// when stored
storedProposal, err := govKeeper.SubmitProposal(ctx, src)
require.NoError(t, err)

// and proposal execute
handler := govKeeper.Router().GetRoute(storedProposal.ProposalRoute())
err = handler(ctx.WithEventManager(em), storedProposal.GetContent())
require.NoError(t, err)

cInfo := wasmKeeper.GetContractInfo(ctx, contractAddress)
require.NotNil(t, cInfo)

assert.Equal(t, uint64(1), cInfo.CodeID)
assert.Equal(t, oneAddress.String(), cInfo.Creator)
assert.Equal(t, otherAddress.String(), cInfo.Admin)
assert.Equal(t, "label", cInfo.Label)
expHistory := []types.ContractCodeHistoryEntry{{
Operation: types.ContractCodeHistoryOperationTypeInit,
CodeID: src.CodeID,
Updated: types.NewAbsoluteTxPosition(ctx),
Msg: src.Msg,
}}
assert.Equal(t, expHistory, wasmKeeper.GetContractHistory(ctx, contractAddress))
// and event
require.Len(t, em.Events(), 3, "%#v", em.Events())
require.Equal(t, types.EventTypeInstantiate, em.Events()[0].Type)
require.Equal(t, types.WasmModuleEventType, em.Events()[1].Type)
require.Equal(t, types.EventTypeGovContractResult, em.Events()[2].Type)
require.Len(t, em.Events()[2].Attributes, 1)
require.NotEmpty(t, em.Events()[2].Attributes[0])
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good test

func TestInstantiateProposal_NoAdmin(t *testing.T) {
ctx, keepers := CreateTestInput(t, false, "staking")
govKeeper, wasmKeeper := keepers.GovKeeper, keepers.WasmKeeper
Expand Down
3 changes: 1 addition & 2 deletions x/wasm/types/authz.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions x/wasm/types/codec.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { //nolint:staticcheck
cdc.RegisterConcrete(&UnpinCodesProposal{}, "wasm/UnpinCodesProposal", nil)
cdc.RegisterConcrete(&StoreCodeProposal{}, "wasm/StoreCodeProposal", nil)
cdc.RegisterConcrete(&InstantiateContractProposal{}, "wasm/InstantiateContractProposal", nil)
cdc.RegisterConcrete(&InstantiateContract2Proposal{}, "wasm/InstantiateContract2Proposal", nil)
cdc.RegisterConcrete(&MigrateContractProposal{}, "wasm/MigrateContractProposal", nil)
cdc.RegisterConcrete(&SudoContractProposal{}, "wasm/SudoContractProposal", nil)
cdc.RegisterConcrete(&ExecuteContractProposal{}, "wasm/ExecuteContractProposal", nil)
Expand Down Expand Up @@ -65,6 +66,7 @@ func RegisterInterfaces(registry types.InterfaceRegistry) {
(*govtypes.Content)(nil),
&StoreCodeProposal{},
&InstantiateContractProposal{},
&InstantiateContract2Proposal{},
&MigrateContractProposal{},
&SudoContractProposal{},
&ExecuteContractProposal{},
Expand Down
3 changes: 1 addition & 2 deletions x/wasm/types/genesis.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions x/wasm/types/ibc.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading