diff --git a/terra/contracts/token-bridge/src/contract.rs b/terra/contracts/token-bridge/src/contract.rs index 298f3ba74..b7e7f8ceb 100644 --- a/terra/contracts/token-bridge/src/contract.rs +++ b/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 { + 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) -> 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) -> StdResult { + 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) -> StdResult { let RegisterChain { chain_id, @@ -508,7 +528,14 @@ fn handle_complete_transfer( ) -> StdResult { 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, diff --git a/terra/contracts/token-bridge/src/msg.rs b/terra/contracts/token-bridge/src/msg.rs index fb2b0bd6d..1ff6adc2e 100644 --- a/terra/contracts/token-bridge/src/msg.rs +++ b/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 { diff --git a/terra/contracts/token-bridge/src/state.rs b/terra/contracts/token-bridge/src/state.rs index ef3d9daef..6bbefa18f 100644 --- a/terra/contracts/token-bridge/src/state.rs +++ b/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, } +impl UpgradeContract { + pub fn deserialize(data: &Vec) -> StdResult { + let data = data.as_slice(); + let new_contract = data.get_u64(24); + Ok(UpgradeContract { + new_contract, + }) + } +} + impl RegisterChain { pub fn deserialize(data: &Vec) -> StdResult { let data = data.as_slice(); diff --git a/terra/tools/migrate.js b/terra/tools/migrate.js index 575b7c695..c2c6c4959 100644 --- a/terra/tools/migrate.js +++ b/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();