Repository: CosmWasm/cosmwasm (rust)

Issue:
Migration of contracts instantiated with WasmMsg::Instantiate fail
When a CW contract is instantiated from command-line, the `migratable` flag can be set to `true`. However, when the contract is instantiated programmatically using `WasmMsg::Instantiate`, there isn't a way to set `migratable` flag, so migration of such contracts fail. 

Pull request:
Add admin field to WasmMsg::Instantiate
Closes #861

Open questions:

- [x] https://github.com/CosmWasm/cosmwasm/issues/861#issuecomment-818663081

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 142c2345d..d12a2b38a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -104,6 +104,8 @@ and this project adheres to
   need one of those, you're probably doing something wrong.
 - cosmwasm-std: Make `label` in `WasmMsg::Instantiate` non-optional to better
   match the Go/database format.
+- cosmwasm-std: Add new field `admin` to `WasmMsg::Instantiate` to fully support
+  `MsgInstantiateContract` from `x/wasm` ([#861]).
 - cosmwasm-std: `Binary::to_array` is now generic over the array length instead
   of the output type. As a consequence the obsolete type `ByteArray` was
   removed. The array length is not restricted to 0-64 anymore.
@@ -171,6 +173,7 @@ and this project adheres to
 [u128]: https://doc.rust-lang.org/std/primitive.u128.html
 [#802]: https://github.com/CosmWasm/cosmwasm/pull/802
 [#871]: https://github.com/CosmWasm/cosmwasm/issues/871
+[#861]: https://github.com/CosmWasm/cosmwasm/issues/861
 
 ### Deprecated
 
diff --git a/contracts/ibc-reflect-send/schema/execute_msg.json b/contracts/ibc-reflect-send/schema/execute_msg.json
index 4a3a5dac7..26c18afbb 100644
--- a/contracts/ibc-reflect-send/schema/execute_msg.json
+++ b/contracts/ibc-reflect-send/schema/execute_msg.json
@@ -573,7 +573,7 @@
           "additionalProperties": false
         },
         {
-          "description": "Instantiates a new contracts from previously uploaded Wasm code.\n\nThis is translated to a [MsgInstantiateContract](https://github.com/CosmWasm/wasmd/blob/v0.14.0/x/wasm/internal/types/tx.proto#L47-L61). `sender` is automatically filled with the current contract's address.",
+          "description": "Instantiates a new contracts from previously uploaded Wasm code.\n\nThis is translated to a [MsgInstantiateContract](https://github.com/CosmWasm/wasmd/blob/v0.16.0-alpha1/x/wasm/internal/types/tx.proto#L47-L61). `sender` is automatically filled with the current contract's address.",
           "type": "object",
           "required": [
             "instantiate"
@@ -588,6 +588,12 @@
                 "send"
               ],
               "properties": {
+                "admin": {
+                  "type": [
+                    "string",
+                    "null"
+                  ]
+                },
                 "code_id": {
                   "type": "integer",
                   "format": "uint64",
diff --git a/contracts/ibc-reflect-send/schema/packet_msg.json b/contracts/ibc-reflect-send/schema/packet_msg.json
index db0ee36d8..8f7d832fa 100644
--- a/contracts/ibc-reflect-send/schema/packet_msg.json
+++ b/contracts/ibc-reflect-send/schema/packet_msg.json
@@ -526,7 +526,7 @@
           "additionalProperties": false
         },
         {
-          "description": "Instantiates a new contracts from previously uploaded Wasm code.\n\nThis is translated to a [MsgInstantiateContract](https://github.com/CosmWasm/wasmd/blob/v0.14.0/x/wasm/internal/types/tx.proto#L47-L61). `sender` is automatically filled with the current contract's address.",
+          "description": "Instantiates a new contracts from previously uploaded Wasm code.\n\nThis is translated to a [MsgInstantiateContract](https://github.com/CosmWasm/wasmd/blob/v0.16.0-alpha1/x/wasm/internal/types/tx.proto#L47-L61). `sender` is automatically filled with the current contract's address.",
           "type": "object",
           "required": [
             "instantiate"
@@ -541,6 +541,12 @@
                 "send"
               ],
               "properties": {
+                "admin": {
+                  "type": [
+                    "string",
+                    "null"
+                  ]
+                },
                 "code_id": {
                   "type": "integer",
                   "format": "uint64",
diff --git a/contracts/ibc-reflect/schema/packet_msg.json b/contracts/ibc-reflect/schema/packet_msg.json
index 612be5473..4c2860046 100644
--- a/contracts/ibc-reflect/schema/packet_msg.json
+++ b/contracts/ibc-reflect/schema/packet_msg.json
@@ -525,7 +525,7 @@
           "additionalProperties": false
         },
         {
-          "description": "Instantiates a new contracts from previously uploaded Wasm code.\n\nThis is translated to a [MsgInstantiateContract](https://github.com/CosmWasm/wasmd/blob/v0.14.0/x/wasm/internal/types/tx.proto#L47-L61). `sender` is automatically filled with the current contract's address.",
+          "description": "Instantiates a new contracts from previously uploaded Wasm code.\n\nThis is translated to a [MsgInstantiateContract](https://github.com/CosmWasm/wasmd/blob/v0.16.0-alpha1/x/wasm/internal/types/tx.proto#L47-L61). `sender` is automatically filled with the current contract's address.",
           "type": "object",
           "required": [
             "instantiate"
@@ -540,6 +540,12 @@
                 "send"
               ],
               "properties": {
+                "admin": {
+                  "type": [
+                    "string",
+                    "null"
+                  ]
+                },
                 "code_id": {
                   "type": "integer",
                   "format": "uint64",
diff --git a/contracts/ibc-reflect/src/contract.rs b/contracts/ibc-reflect/src/contract.rs
index 33c9727e0..5b26c7e33 100644
--- a/contracts/ibc-reflect/src/contract.rs
+++ b/contracts/ibc-reflect/src/contract.rs
@@ -420,14 +420,16 @@ mod tests {
         // and set up a reflect account
         assert_eq!(1, res.messages.len());
         if let CosmosMsg::Wasm(WasmMsg::Instantiate {
+            admin,
             code_id,
             msg,
             send,
             label,
         }) = &res.messages[0]
         {
-            assert_eq!(&REFLECT_ID, code_id);
-            assert_eq!(0, send.len());
+            assert_eq!(*admin, None);
+            assert_eq!(*code_id, REFLECT_ID);
+            assert_eq!(send.len(), 0);
             assert!(label.contains(channel_id));
             // parse the message - should callback with proper channel_id
             let rmsg: ReflectInstantiateMsg = from_slice(&msg).unwrap();
diff --git a/contracts/reflect/schema/execute_msg.json b/contracts/reflect/schema/execute_msg.json
index c80689fe6..8d947df2b 100644
--- a/contracts/reflect/schema/execute_msg.json
+++ b/contracts/reflect/schema/execute_msg.json
@@ -608,7 +608,7 @@
           "additionalProperties": false
         },
         {
-          "description": "Instantiates a new contracts from previously uploaded Wasm code.\n\nThis is translated to a [MsgInstantiateContract](https://github.com/CosmWasm/wasmd/blob/v0.14.0/x/wasm/internal/types/tx.proto#L47-L61). `sender` is automatically filled with the current contract's address.",
+          "description": "Instantiates a new contracts from previously uploaded Wasm code.\n\nThis is translated to a [MsgInstantiateContract](https://github.com/CosmWasm/wasmd/blob/v0.16.0-alpha1/x/wasm/internal/types/tx.proto#L47-L61). `sender` is automatically filled with the current contract's address.",
           "type": "object",
           "required": [
             "instantiate"
@@ -623,6 +623,12 @@
                 "send"
               ],
               "properties": {
+                "admin": {
+                  "type": [
+                    "string",
+                    "null"
+                  ]
+                },
                 "code_id": {
                   "type": "integer",
                   "format": "uint64",
diff --git a/contracts/reflect/schema/response_for__custom_msg.json b/contracts/reflect/schema/response_for__custom_msg.json
index 162295622..460edb32a 100644
--- a/contracts/reflect/schema/response_for__custom_msg.json
+++ b/contracts/reflect/schema/response_for__custom_msg.json
@@ -596,7 +596,7 @@
           "additionalProperties": false
         },
         {
-          "description": "Instantiates a new contracts from previously uploaded Wasm code.\n\nThis is translated to a [MsgInstantiateContract](https://github.com/CosmWasm/wasmd/blob/v0.14.0/x/wasm/internal/types/tx.proto#L47-L61). `sender` is automatically filled with the current contract's address.",
+          "description": "Instantiates a new contracts from previously uploaded Wasm code.\n\nThis is translated to a [MsgInstantiateContract](https://github.com/CosmWasm/wasmd/blob/v0.16.0-alpha1/x/wasm/internal/types/tx.proto#L47-L61). `sender` is automatically filled with the current contract's address.",
           "type": "object",
           "required": [
             "instantiate"
@@ -611,6 +611,12 @@
                 "send"
               ],
               "properties": {
+                "admin": {
+                  "type": [
+                    "string",
+                    "null"
+                  ]
+                },
                 "code_id": {
                   "type": "integer",
                   "format": "uint64",
diff --git a/packages/std/schema/cosmos_msg.json b/packages/std/schema/cosmos_msg.json
index 255188a3f..9c0bb798d 100644
--- a/packages/std/schema/cosmos_msg.json
+++ b/packages/std/schema/cosmos_msg.json
@@ -288,7 +288,7 @@
           "additionalProperties": false
         },
         {
-          "description": "Instantiates a new contracts from previously uploaded Wasm code.\n\nThis is translated to a [MsgInstantiateContract](https://github.com/CosmWasm/wasmd/blob/v0.14.0/x/wasm/internal/types/tx.proto#L47-L61). `sender` is automatically filled with the current contract's address.",
+          "description": "Instantiates a new contracts from previously uploaded Wasm code.\n\nThis is translated to a [MsgInstantiateContract](https://github.com/CosmWasm/wasmd/blob/v0.16.0-alpha1/x/wasm/internal/types/tx.proto#L47-L61). `sender` is automatically filled with the current contract's address.",
           "type": "object",
           "required": [
             "instantiate"
@@ -303,6 +303,12 @@
                 "send"
               ],
               "properties": {
+                "admin": {
+                  "type": [
+                    "string",
+                    "null"
+                  ]
+                },
                 "code_id": {
                   "type": "integer",
                   "format": "uint64",
diff --git a/packages/std/src/results/cosmos_msg.rs b/packages/std/src/results/cosmos_msg.rs
index 234b87dc3..9e6811575 100644
--- a/packages/std/src/results/cosmos_msg.rs
+++ b/packages/std/src/results/cosmos_msg.rs
@@ -107,9 +107,10 @@ pub enum WasmMsg {
     },
     /// Instantiates a new contracts from previously uploaded Wasm code.
     ///
-    /// This is translated to a [MsgInstantiateContract](https://github.com/CosmWasm/wasmd/blob/v0.14.0/x/wasm/internal/types/tx.proto#L47-L61).
+    /// This is translated to a [MsgInstantiateContract](https://github.com/CosmWasm/wasmd/blob/v0.16.0-alpha1/x/wasm/internal/types/tx.proto#L47-L61).
     /// `sender` is automatically filled with the current contract's address.
     Instantiate {
+        admin: Option<String>,
         code_id: u64,
         /// msg is the JSON-encoded InstantiateMsg struct (as raw Binary)
         msg: Binary,
@@ -133,7 +134,9 @@ pub enum WasmMsg {
     },
 }
 
-/// Shortcut helper as the construction of WasmMsg::Instantiate can be quite verbose in contract code
+/// Shortcut helper as the construction of WasmMsg::Instantiate can be quite verbose in contract code.
+///
+/// When using this, `admin` is always unset. If you need more flexibility, create the message directly.
 pub fn wasm_instantiate<T>(
     code_id: u64,
     msg: &T,
@@ -145,6 +148,7 @@ where
 {
     let payload = to_binary(msg)?;
     Ok(WasmMsg::Instantiate {
+        admin: None,
         code_id,
         msg: payload,
         send,


Test patch:
diff --git a/contracts/ibc-reflect/tests/integration.rs b/contracts/ibc-reflect/tests/integration.rs
index b6028b276..b1085ccd4 100644
--- a/contracts/ibc-reflect/tests/integration.rs
+++ b/contracts/ibc-reflect/tests/integration.rs
@@ -124,14 +124,16 @@ fn proper_handshake_flow() {
     // and set up a reflect account
     assert_eq!(1, res.messages.len());
     if let CosmosMsg::Wasm(WasmMsg::Instantiate {
+        admin,
         code_id,
         msg,
         send,
         label,
     }) = &res.messages[0]
     {
-        assert_eq!(&REFLECT_ID, code_id);
-        assert_eq!(0, send.len());
+        assert_eq!(*admin, None);
+        assert_eq!(*code_id, REFLECT_ID);
+        assert_eq!(send.len(), 0);
         assert!(label.contains(channel_id));
         // parse the message - should callback with proper channel_id
         let rmsg: ReflectInstantiateMsg = from_slice(&msg).unwrap();