Pārlūkot izejas kodu

terra/token_bridge: upgradability

Change-Id: Ib41583c0d99aad0e77fb970bc9ee0f7be56f6b4e
Reisen 4 gadi atpakaļ
vecāks
revīzija
3607884556

+ 29 - 6
terra/contracts/token-bridge/src/contract.rs

@@ -26,6 +26,7 @@ use crate::{
     msg::{
         ExecuteMsg,
         InstantiateMsg,
+        MigrateMsg,
         QueryMsg,
     },
     state::{
@@ -46,6 +47,7 @@ use crate::{
         RegisterChain,
         TokenBridgeMessage,
         TransferInfo,
+        UpgradeContract,
     },
 };
 use wormhole::{
@@ -105,6 +107,11 @@ const CHAIN_ID: u16 = 3;
 
 const WRAPPED_ASSET_UPDATING: &str = "updating";
 
+#[cfg_attr(not(feature = "library"), entry_point)]
+pub fn migrate(_deps: DepsMut, _env: Env, _msg: MigrateMsg) -> StdResult<Response> {
+    Ok(Response::default())
+}
+
 #[cfg_attr(not(feature = "library"), entry_point)]
 pub fn instantiate(
     deps: DepsMut,
@@ -473,10 +480,23 @@ fn handle_governance_payload(deps: DepsMut, env: Env, data: &Vec<u8>) -> StdResu
 
     match gov_packet.action {
         1u8 => handle_register_chain(deps, env, &gov_packet.payload),
+        2u8 => handle_upgrade_contract(deps, env, &gov_packet.payload),
         _ => ContractError::InvalidVAAAction.std_err(),
     }
 }
 
+fn handle_upgrade_contract(_deps: DepsMut, env: Env, data: &Vec<u8>) -> StdResult<Response> {
+    let UpgradeContract { new_contract } = UpgradeContract::deserialize(&data)?;
+
+    Ok(Response::new()
+        .add_message(CosmosMsg::Wasm(WasmMsg::Migrate {
+            contract_addr: env.contract.address.to_string(),
+            new_code_id: new_contract,
+            msg: to_binary(&MigrateMsg {})?,
+        }))
+        .add_attribute("action", "contract_upgrade"))
+}
+
 fn handle_register_chain(deps: DepsMut, _env: Env, data: &Vec<u8>) -> StdResult<Response> {
     let RegisterChain {
         chain_id,
@@ -508,7 +528,14 @@ fn handle_complete_transfer(
 ) -> StdResult<Response> {
     let transfer_info = TransferInfo::deserialize(&data)?;
     match transfer_info.token_address.as_slice()[0] {
-        1 => handle_complete_transfer_token_native(deps, env, info, emitter_chain, emitter_address, data),
+        1 => handle_complete_transfer_token_native(
+            deps,
+            env,
+            info,
+            emitter_chain,
+            emitter_address,
+            data,
+        ),
         _ => handle_complete_transfer_token(deps, env, info, emitter_chain, emitter_address, data),
     }
 }
@@ -643,7 +670,6 @@ fn handle_complete_transfer_token(
     }
 }
 
-
 fn handle_complete_transfer_token_native(
     deps: DepsMut,
     _env: Env,
@@ -659,9 +685,7 @@ fn handle_complete_transfer_token_native(
 
     // must be sent by a registered token bridge contract
     if expected_contract != emitter_address {
-        return Err(StdError::generic_err(
-            "invalid emitter",
-        ));
+        return Err(StdError::generic_err("invalid emitter"));
     }
 
     if transfer_info.recipient_chain != CHAIN_ID {
@@ -717,7 +741,6 @@ fn handle_complete_transfer_token_native(
         .add_attribute("amount", amount.to_string()))
 }
 
-
 fn handle_initiate_transfer(
     deps: DepsMut,
     env: Env,

+ 5 - 0
terra/contracts/token-bridge/src/msg.rs

@@ -52,6 +52,11 @@ pub enum ExecuteMsg {
     },
 }
 
+#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
+#[serde(rename_all = "snake_case")]
+pub struct MigrateMsg {
+}
+
 #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
 #[serde(rename_all = "snake_case")]
 pub enum QueryMsg {

+ 14 - 0
terra/contracts/token-bridge/src/state.rs

@@ -239,11 +239,25 @@ impl AssetMeta {
     }
 }
 
+pub struct UpgradeContract {
+    pub new_contract: u64,
+}
+
 pub struct RegisterChain {
     pub chain_id: u16,
     pub chain_address: Vec<u8>,
 }
 
+impl UpgradeContract {
+    pub fn deserialize(data: &Vec<u8>) -> StdResult<Self> {
+        let data = data.as_slice();
+        let new_contract = data.get_u64(24);
+        Ok(UpgradeContract {
+            new_contract,
+        })
+    }
+}
+
 impl RegisterChain {
     pub fn deserialize(data: &Vec<u8>) -> StdResult<Self> {
         let data = data.as_slice();

+ 68 - 2
terra/tools/migrate.js

@@ -25,7 +25,6 @@ async function main() {
   const hardcodedGas = {
     "wormhole.wasm": 5000000,
   };
-
   // Deploy Wormhole alone.
   const file = "wormhole.wasm";
   const contract_bytes = readFileSync(`../artifacts/${file}`);
@@ -105,7 +104,34 @@ async function main() {
     console.log("Failed to Execute");
   }
 
-  const upgradeVAA = '010000000001008928c70a029a924d334a24587e9d2ddbcfa7250d7ba61200e86b16966ef2bbd675fb759aa7a47c6392482ef073e9a6d7c4980dc53ed6f90fc84331486e284912000000000100000001000100000000000000000000000000000000000000000000000000000000000000040000000004e78c580000000000000000000000000000000000000000000000000000000000436f72650100030000000000000000000000000000000000000000000000000000000000000005';
+  // Perform a Guardian Set Upgrade to check the following
+  // flow with six guardians rather than the default one.
+  const guardianUpgradeVAA = '01000000000100f8547caf1d1263e6b4742aef05691a9e2a7aa082bb2f1deb3850e43b801a87044cf786924d8adff5553f31b41149f94a32b568321390450f12c31aa15c2f941101000000010000000100010000000000000000000000000000000000000000000000000000000000000004000000000227cc370000000000000000000000000000000000000000000000000000000000436f72650200000000000106befa429d57cd18b7f8a4d91a2da9ab4af05d0fbe4ba0c2db9a26208b3bb1a50b01b16941c10d76db4ba0c2db9a26208b3bb1a50b01b16941c10d76db4ba0c2db9a26208b3bb1a50b01b16941c10d76db4ba0c2db9a26208b3bb1a50b01b16941c10d76db4ba0c2db9a26208b3bb1a50b01b16941c10d76db';
+
+  await wallet
+    .createAndSignTx({
+      msgs: [
+        new MsgExecuteContract(
+          wallet.key.accAddress,
+          "terra18vd8fpwxzck93qlwghaj6arh4p7c5n896xzem5",
+          {
+            submit_v_a_a: {
+              vaa: Buffer.from(guardianUpgradeVAA, "hex").toString(
+                "base64"
+              ),
+            },
+          },
+          { uluna: 1000 }
+        ),
+      ],
+      memo: "",
+    })
+    .then((tx) => terra.tx.broadcast(tx))
+    .then((rs) => console.log(rs));
+
+
+  // Upgrace VAA with 5 signatures to test qurom threshold.
+  const upgradeVAA = '0100000001050058f5e6a55261e137b12405eb5acf3e4670101c3b7561c6694d7116b6afec85b153f90992fb5e0d6d5a79506f524324fb21894ef655367cc37a572b07a9bfe43301011dba8dca119605dcd30efaf7c4f6980afdf5d58f9625648b652288505abe19be11eabe7424e69d3dae682a84c58208237a975c5ed7757613f546763e14db621200021dba8dca119605dcd30efaf7c4f6980afdf5d58f9625648b652288505abe19be11eabe7424e69d3dae682a84c58208237a975c5ed7757613f546763e14db621200031dba8dca119605dcd30efaf7c4f6980afdf5d58f9625648b652288505abe19be11eabe7424e69d3dae682a84c58208237a975c5ed7757613f546763e14db621200041dba8dca119605dcd30efaf7c4f6980afdf5d58f9625648b652288505abe19be11eabe7424e69d3dae682a84c58208237a975c5ed7757613f546763e14db6212000000000100000001000100000000000000000000000000000000000000000000000000000000000000040000000000a653200000000000000000000000000000000000000000000000000000000000436f72650100030000000000000000000000000000000000000000000000000000000000000005';
 
   // Perform a decentralised update with a signed VAA.
   await wallet
@@ -128,6 +154,46 @@ async function main() {
     })
     .then((tx) => terra.tx.broadcast(tx))
     .then((rs) => console.log(rs));
+
+  // Set the Admin of the Token Bridge to itself.
+  await wallet
+    .createAndSignTx({
+      msgs: [
+        new MsgUpdateContractAdmin(
+          wallet.key.accAddress,
+          "terra10pyejy66429refv3g35g2t7am0was7ya7kz2a4",
+          "terra10pyejy66429refv3g35g2t7am0was7ya7kz2a4"
+        ),
+      ],
+      memo: "",
+    })
+    .then((tx) => terra.tx.broadcast(tx))
+    .then((rs) => console.log(rs));
+
+  // Upgrade VAA for the Token Bridge.
+  const upgradeTokenVAA = '01000000010500088c284fe2adf0976511290902cbb1dd29239dcd9cb343936c8e76825777db0912eecb7d1be70ddc8b15091834bc0626ea52cc82a202c71f1dc2ff6acffa111b0101b9c36107b2fa1ad413ec6a71aca58d4cd44dea28b692c242805ff0c6df7ce0cb5648f92f5a17a1e1cd2e6df89abb236716d9556a03e6ec5d2ad463cd326d1b830102b9c36107b2fa1ad413ec6a71aca58d4cd44dea28b692c242805ff0c6df7ce0cb5648f92f5a17a1e1cd2e6df89abb236716d9556a03e6ec5d2ad463cd326d1b830103b9c36107b2fa1ad413ec6a71aca58d4cd44dea28b692c242805ff0c6df7ce0cb5648f92f5a17a1e1cd2e6df89abb236716d9556a03e6ec5d2ad463cd326d1b830104b9c36107b2fa1ad413ec6a71aca58d4cd44dea28b692c242805ff0c6df7ce0cb5648f92f5a17a1e1cd2e6df89abb236716d9556a03e6ec5d2ad463cd326d1b8301000000010000000100010000000000000000000000000000000000000000000000000000000000000004000000000441f94100000000000000000000000000000000000000000000546f6b656e4272696467650200030000000000000000000000000000000000000000000000000000000000000005';
+
+  // Perform a decentralised update with a signed VAA.
+  await wallet
+    .createAndSignTx({
+      msgs: [
+        new MsgExecuteContract(
+          wallet.key.accAddress,
+          "terra10pyejy66429refv3g35g2t7am0was7ya7kz2a4",
+          {
+            submit_vaa: {
+              data: Buffer.from(upgradeTokenVAA, "hex").toString(
+                "base64"
+              ),
+            },
+          },
+          { uluna: 1000 }
+        ),
+      ],
+      memo: "",
+    })
+    .then((tx) => terra.tx.broadcast(tx))
+    .then((rs) => console.log(rs));
 }
 
 main();