token.rs 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931
  1. //! Parsers for Token bridge VAAs.
  2. //!
  3. //! Token bridging relies on VAA's that indicate custody/lockup/burn events in order to maintain
  4. //! token parity between multiple chains. These parsers can be used to read these VAAs. It also
  5. //! defines the Governance actions that this module supports, namely contract upgrades and chain
  6. //! registrations.
  7. use bstr::BString;
  8. use serde::{Deserialize, Serialize};
  9. use serde_wormhole::RawMessage;
  10. use crate::{Address, Amount, Chain};
  11. /// Represents a non-governance action targeted at the token bridge.
  12. ///
  13. /// The generic parameter `P` indicates the type of the payload for the `TransferWithPayload`
  14. /// variant. This defaults to `Box<RawMessage>` as that provides the most flexibility when
  15. /// deserializing the payload and avoids leaking lifetime parameters higher up the stack. However,
  16. /// users who are serializing to or deserializing from the serde_wormhole data format may want to
  17. /// use a `&RawMessage` to avoid unnecessary memory allocations. When the type of the payload is
  18. /// known and is serialized in the same data format as the rest of the message, that type can be
  19. /// used as the generic parameter to deserialize the message and the payload together.
  20. #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
  21. pub enum Message<P = Box<RawMessage>> {
  22. /// The Transfer message contains specifics detailing a token lock up on a sending chain. Chains
  23. /// that are attempting to initiate a transfer must lock up tokens in some manner, such as in a
  24. /// custody account or via burning, before emitting this message.
  25. #[serde(rename = "1")]
  26. Transfer {
  27. /// The amount being transferred.
  28. amount: Amount,
  29. /// Address of the token. Left-zero-padded if shorter than 32 bytes.
  30. token_address: Address,
  31. /// Chain ID of the token.
  32. token_chain: Chain,
  33. /// Address of the recipient. Left-zero-padded if shorter than 32 bytes.
  34. recipient: Address,
  35. /// Chain ID of the recipient.
  36. recipient_chain: Chain,
  37. /// Amount that the user is willing to pay as the relayer fee. Must be <= `amount`.
  38. fee: Amount,
  39. },
  40. /// Contains information about a token and its origin chain.
  41. #[serde(rename = "2")]
  42. AssetMeta {
  43. /// Address of the token. Left-zero-padded if shorter than 32 bytes.
  44. token_address: Address,
  45. /// Chain ID of the token.
  46. token_chain: Chain,
  47. /// Number of decimals in the token.
  48. decimals: u8,
  49. /// Symbol of the token.
  50. #[serde(with = "crate::arraystring")]
  51. symbol: BString,
  52. /// Name of the token.
  53. #[serde(with = "crate::arraystring")]
  54. name: BString,
  55. },
  56. /// Similar to `Transfer` but also includes an arbitrary payload.
  57. ///
  58. /// # Examples
  59. ///
  60. /// Deserialize a `TransferWithPayload` message using the `serde_wormhole` crate:
  61. ///
  62. /// ```
  63. /// # fn example() -> anyhow::Result<()> {
  64. /// # use wormhole_sdk::{Address, Amount, Chain, vaa::Signature, GOVERNANCE_EMITTER};
  65. /// #
  66. /// # let data = [
  67. /// # 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xb0, 0x72, 0x50, 0x5b, 0x5b, 0x99, 0x9c, 0x1d,
  68. /// # 0x08, 0x90, 0x5c, 0x02, 0xe2, 0xb6, 0xb2, 0x83, 0x2e, 0xf7, 0x2c, 0x0b, 0xa6, 0xc8, 0xdb,
  69. /// # 0x4f, 0x77, 0xfe, 0x45, 0x7e, 0xf2, 0xb3, 0xd0, 0x53, 0x41, 0x0b, 0x1e, 0x92, 0xa9, 0x19,
  70. /// # 0x4d, 0x92, 0x10, 0xdf, 0x24, 0xd9, 0x87, 0xac, 0x83, 0xd7, 0xb6, 0xf0, 0xc2, 0x1c, 0xe9,
  71. /// # 0x0f, 0x8b, 0xc1, 0x86, 0x9d, 0xe0, 0x89, 0x8b, 0xda, 0x7e, 0x98, 0x01, 0x00, 0x00, 0x00,
  72. /// # 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  73. /// # 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  74. /// # 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01, 0x3c,
  75. /// # 0x1b, 0xfa, 0x00, 0x03, 0x99, 0x30, 0x29, 0x01, 0x67, 0xf3, 0x48, 0x6a, 0xf6, 0x4c, 0xdd,
  76. /// # 0x07, 0x64, 0xa1, 0x6a, 0xca, 0xcc, 0xc5, 0x64, 0x2a, 0x66, 0x71, 0xaa, 0x87, 0x98, 0x64,
  77. /// # 0x0c, 0x25, 0x1f, 0x39, 0x73, 0x25, 0x12, 0x98, 0x15, 0xe5, 0x79, 0xdb, 0xd8, 0x25, 0xfd,
  78. /// # 0x72, 0x58, 0x99, 0x97, 0xd1, 0x78, 0xb6, 0x2a, 0x57, 0x47, 0xab, 0xcf, 0x51, 0x62, 0xa5,
  79. /// # 0xb7, 0xec, 0x19, 0x4e, 0x03, 0x51, 0x41, 0x18, 0x00, 0x08, 0xa4, 0x7e, 0xa2, 0x49, 0xd4,
  80. /// # 0xf0, 0x56, 0x6f, 0xbd, 0x12, 0x77, 0xfe, 0xa8, 0x6e, 0x92, 0x81, 0x3a, 0x35, 0x90, 0x3b,
  81. /// # 0x29, 0x73, 0x4d, 0x75, 0x56, 0x0a, 0xfe, 0x70, 0xb0, 0xb9, 0x10, 0x33, 0x00, 0x14, 0x47,
  82. /// # 0x3e, 0x51, 0x74, 0x32, 0xbc, 0x3f, 0xb3, 0xf9, 0x82, 0xbb, 0xf3, 0xc9, 0x43, 0x41, 0xcf,
  83. /// # 0x74, 0x24, 0xff, 0xa4, 0x02, 0x35, 0xbe, 0xb1, 0x7c, 0x47, 0x16, 0xba, 0xbc, 0xaa, 0xbe,
  84. /// # 0x99, 0x54, 0xa2, 0x97, 0xbe, 0x2a, 0xed, 0xae, 0x91, 0x95, 0xb9, 0x6a, 0x8a, 0xba, 0xbd,
  85. /// # 0x3a, 0xc1, 0xa4, 0xd1, 0x96, 0x0a, 0xf9, 0xab, 0x92, 0x42, 0x0d, 0x41, 0x33, 0xe5, 0xa8,
  86. /// # 0x37, 0x32, 0xd3, 0xc3, 0xb8, 0xf3, 0x93, 0xd7, 0xc0, 0x9e, 0xe8, 0x87, 0xae, 0x16, 0xbf,
  87. /// # 0xfa, 0x5e, 0x70, 0xea, 0x36, 0xa2, 0x82, 0x37, 0x1d, 0x46, 0x81, 0x94, 0x10, 0x34, 0xb1,
  88. /// # 0xad, 0x0f, 0x4b, 0xc9, 0x17, 0x1e, 0x91, 0x25, 0x11,
  89. /// # ];
  90. /// use serde_wormhole::RawMessage;
  91. /// use wormhole_sdk::{token::Message, Vaa};
  92. ///
  93. /// let msg = serde_wormhole::from_slice::<Vaa<Message<&RawMessage>>>(&data)?;
  94. /// match msg.payload {
  95. /// Message::TransferWithPayload { payload, .. } => {
  96. /// // Handle the payload.
  97. /// # assert_eq!(&data[256..], payload.get())
  98. /// }
  99. /// _ => {
  100. /// // Handle other message types.
  101. /// # panic!("unexpected message type")
  102. /// }
  103. /// }
  104. /// #
  105. /// # Ok(())
  106. /// # }
  107. /// #
  108. /// # example().unwrap();
  109. /// ```
  110. ///
  111. /// Deserialize a `TransferWithPayload` message using `serde_json`:
  112. ///
  113. /// ```
  114. /// # fn example() -> anyhow::Result<()> {
  115. /// # use serde_wormhole::RawMessage;
  116. /// # use wormhole_sdk::{Address, Amount, Chain, vaa::Signature, GOVERNANCE_EMITTER};
  117. /// # let tx_payload = [
  118. /// # 0x93, 0xd7, 0xc0, 0x9e, 0xe8, 0x87, 0xae, 0x16, 0xbf, 0xfa, 0x5e, 0x70, 0xea, 0x36, 0xa2,
  119. /// # 0x82, 0x37, 0x1d, 0x46, 0x81, 0x94, 0x10, 0x34, 0xb1, 0xad, 0x0f, 0x4b, 0xc9,
  120. /// # ];
  121. /// #
  122. /// # let vaa = Vaa {
  123. /// # version: 1,
  124. /// # guardian_set_index: 0,
  125. /// # signatures: Vec::new(),
  126. /// # timestamp: 1,
  127. /// # nonce: 1,
  128. /// # emitter_chain: Chain::Solana,
  129. /// # emitter_address: GOVERNANCE_EMITTER,
  130. /// # sequence: 20_716_538,
  131. /// # consistency_level: 0,
  132. /// # payload: Message::TransferWithPayload {
  133. /// # amount: Amount([0xcc; 32]),
  134. /// # token_address: Address([0x22; 32]),
  135. /// # token_chain: Chain::Algorand,
  136. /// # recipient: Address([0x19; 32]),
  137. /// # recipient_chain: Chain::Osmosis,
  138. /// # sender_address: Address([0xfe; 32]),
  139. /// # payload: <Box<RawMessage>>::from(tx_payload.to_vec()),
  140. /// # },
  141. /// # };
  142. /// #
  143. /// # let data = serde_json::to_vec(&vaa)?;
  144. /// use anyhow::anyhow;
  145. /// use wormhole_sdk::{token::Message, Vaa};
  146. ///
  147. /// let msg = serde_json::from_slice::<Vaa<Message>>(&data)?;
  148. /// # assert_eq!(vaa, msg);
  149. /// match msg.payload {
  150. /// Message::TransferWithPayload { payload, .. } => {
  151. /// // Handle the payload.
  152. /// # assert_eq!(&tx_payload[..], payload.get())
  153. /// }
  154. /// _ => {
  155. /// // Handle other message types.
  156. /// # panic!("unexpected message type")
  157. /// }
  158. /// }
  159. /// #
  160. /// # Ok(())
  161. /// # }
  162. /// #
  163. /// # example().unwrap();
  164. /// ```
  165. #[serde(rename = "3")]
  166. TransferWithPayload {
  167. /// The amount being transferred.
  168. amount: Amount,
  169. /// Address of the token. Left-zero-padded if shorter than 32 bytes.
  170. token_address: Address,
  171. /// Chain ID of the token.
  172. token_chain: Chain,
  173. /// Address of the recipient. Left-zero-padded if shorter than 32 bytes.
  174. recipient: Address,
  175. /// Chain ID of the recipient.
  176. recipient_chain: Chain,
  177. /// The identity of the sender sending the payload.
  178. sender_address: Address,
  179. /// The payload to be included with the transfer.
  180. payload: P,
  181. },
  182. }
  183. /// Represents a governance action targeted at the token bridge.
  184. #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
  185. pub enum Action {
  186. /// Registers an emitter address for a particular chain on a different chain. An emitter
  187. /// address must be registered for a chain and must match the emitter address in the VAA before
  188. /// the token bridge will accept VAAs from that chain.
  189. #[serde(rename = "1")]
  190. RegisterChain {
  191. chain: Chain,
  192. emitter_address: Address,
  193. },
  194. /// Upgrades the token bridge contract to a new address.
  195. #[serde(rename = "2")]
  196. ContractUpgrade { new_contract: Address },
  197. }
  198. /// Represents the payload for a governance VAA targeted at the token bridge.
  199. #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
  200. pub struct GovernancePacket {
  201. /// The chain on which the governance action should be carried out.
  202. pub chain: Chain,
  203. /// The actual governance action to be carried out.
  204. pub action: Action,
  205. }
  206. // MODULE = "TokenBridge"
  207. pub const MODULE: [u8; 32] = *b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00TokenBridge";
  208. // The wire format for GovernancePackets is wonky and doesn't lend itself well to auto-deriving
  209. // Serialize / Deserialize so we implement it manually here.
  210. mod governance_packet_impl {
  211. use std::fmt;
  212. use serde::{
  213. de::{Error, MapAccess, SeqAccess, Visitor},
  214. ser::SerializeStruct,
  215. Deserialize, Deserializer, Serialize, Serializer,
  216. };
  217. use crate::{
  218. token::{Action, GovernancePacket, MODULE},
  219. Address, Chain,
  220. };
  221. struct Module;
  222. impl Serialize for Module {
  223. fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
  224. where
  225. S: Serializer,
  226. {
  227. MODULE.serialize(serializer)
  228. }
  229. }
  230. impl<'de> Deserialize<'de> for Module {
  231. fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
  232. where
  233. D: Deserializer<'de>,
  234. {
  235. let arr = <[u8; 32]>::deserialize(deserializer)?;
  236. if arr == MODULE {
  237. Ok(Module)
  238. } else {
  239. Err(Error::custom(
  240. "invalid governance module, expected \"TokenBridge\"",
  241. ))
  242. }
  243. }
  244. }
  245. #[derive(Serialize, Deserialize)]
  246. struct ContractUpgrade {
  247. new_contract: Address,
  248. }
  249. #[derive(Serialize, Deserialize)]
  250. struct RegisterChain {
  251. chain: Chain,
  252. emitter_address: Address,
  253. }
  254. impl Serialize for GovernancePacket {
  255. fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
  256. where
  257. S: Serializer,
  258. {
  259. let mut seq = serializer.serialize_struct("GovernancePacket", 4)?;
  260. seq.serialize_field("module", &Module)?;
  261. // The wire format encodes the action before the chain and then appends the actual
  262. // action payload.
  263. match self.action.clone() {
  264. Action::RegisterChain {
  265. chain,
  266. emitter_address,
  267. } => {
  268. seq.serialize_field("action", &1u8)?;
  269. seq.serialize_field("chain", &self.chain)?;
  270. seq.serialize_field(
  271. "payload",
  272. &RegisterChain {
  273. chain,
  274. emitter_address,
  275. },
  276. )?;
  277. }
  278. Action::ContractUpgrade { new_contract } => {
  279. seq.serialize_field("action", &2u8)?;
  280. seq.serialize_field("chain", &self.chain)?;
  281. seq.serialize_field("payload", &ContractUpgrade { new_contract })?;
  282. }
  283. }
  284. seq.end()
  285. }
  286. }
  287. struct GovernancePacketVisitor;
  288. impl<'de> Visitor<'de> for GovernancePacketVisitor {
  289. type Value = GovernancePacket;
  290. fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
  291. f.write_str("struct GovernancePacket")
  292. }
  293. #[inline]
  294. fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
  295. where
  296. A: SeqAccess<'de>,
  297. {
  298. static EXPECTING: &str = "struct GovernancePacket with 4 elements";
  299. let _: Module = seq
  300. .next_element()?
  301. .ok_or_else(|| Error::invalid_length(0, &EXPECTING))?;
  302. let act: u8 = seq
  303. .next_element()?
  304. .ok_or_else(|| Error::invalid_length(1, &EXPECTING))?;
  305. let chain = seq
  306. .next_element()?
  307. .ok_or_else(|| Error::invalid_length(2, &EXPECTING))?;
  308. let action = match act {
  309. 1 => {
  310. let RegisterChain {
  311. chain,
  312. emitter_address,
  313. } = seq
  314. .next_element()?
  315. .ok_or_else(|| Error::invalid_length(3, &EXPECTING))?;
  316. Action::RegisterChain {
  317. chain,
  318. emitter_address,
  319. }
  320. }
  321. 2 => {
  322. let ContractUpgrade { new_contract } = seq
  323. .next_element()?
  324. .ok_or_else(|| Error::invalid_length(3, &EXPECTING))?;
  325. Action::ContractUpgrade { new_contract }
  326. }
  327. v => {
  328. return Err(Error::custom(format_args!(
  329. "invalid value: {v}, expected one of 1, 2"
  330. )))
  331. }
  332. };
  333. Ok(GovernancePacket { chain, action })
  334. }
  335. fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
  336. where
  337. A: MapAccess<'de>,
  338. {
  339. #[derive(Serialize, Deserialize)]
  340. #[serde(rename_all = "snake_case")]
  341. enum Field {
  342. Module,
  343. Action,
  344. Chain,
  345. Payload,
  346. }
  347. let mut module = None;
  348. let mut chain = None;
  349. let mut action = None;
  350. let mut payload = None;
  351. while let Some(key) = map.next_key::<Field>()? {
  352. match key {
  353. Field::Module => {
  354. if module.is_some() {
  355. return Err(Error::duplicate_field("module"));
  356. }
  357. module = map.next_value::<Module>().map(Some)?;
  358. }
  359. Field::Action => {
  360. if action.is_some() {
  361. return Err(Error::duplicate_field("action"));
  362. }
  363. action = map.next_value::<u8>().map(Some)?;
  364. }
  365. Field::Chain => {
  366. if chain.is_some() {
  367. return Err(Error::duplicate_field("chain"));
  368. }
  369. chain = map.next_value().map(Some)?;
  370. }
  371. Field::Payload => {
  372. if payload.is_some() {
  373. return Err(Error::duplicate_field("payload"));
  374. }
  375. let a = action.as_ref().copied().ok_or_else(|| {
  376. Error::custom("`action` must be known before deserializing `payload`")
  377. })?;
  378. let p = match a {
  379. 1 => {
  380. let RegisterChain {
  381. chain,
  382. emitter_address,
  383. } = map.next_value()?;
  384. Action::RegisterChain {
  385. chain,
  386. emitter_address,
  387. }
  388. }
  389. 2 => {
  390. let ContractUpgrade { new_contract } = map.next_value()?;
  391. Action::ContractUpgrade { new_contract }
  392. }
  393. v => {
  394. return Err(Error::custom(format_args!(
  395. "invalid action: {v}, expected one of: 1, 2"
  396. )))
  397. }
  398. };
  399. payload = Some(p);
  400. }
  401. }
  402. }
  403. let _ = module.ok_or_else(|| Error::missing_field("module"))?;
  404. let chain = chain.ok_or_else(|| Error::missing_field("chain"))?;
  405. let action = payload.ok_or_else(|| Error::missing_field("payload"))?;
  406. Ok(GovernancePacket { chain, action })
  407. }
  408. }
  409. impl<'de> Deserialize<'de> for GovernancePacket {
  410. fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
  411. where
  412. D: Deserializer<'de>,
  413. {
  414. const FIELDS: &[&str] = &["module", "action", "chain", "payload"];
  415. deserializer.deserialize_struct("GovernancePacket", FIELDS, GovernancePacketVisitor)
  416. }
  417. }
  418. }
  419. #[cfg(test)]
  420. mod test {
  421. use serde_wormhole::RawMessage;
  422. use crate::{vaa::Signature, Vaa, GOVERNANCE_EMITTER};
  423. use super::*;
  424. #[test]
  425. pub fn transfer() {
  426. let payload = [
  427. 0x01, 0xfa, 0x22, 0x8b, 0x3d, 0xf3, 0x59, 0x21, 0xa1, 0xc9, 0x39, 0xad, 0x9c, 0x54,
  428. 0xe1, 0x2f, 0x87, 0xc6, 0x27, 0x25, 0xd1, 0xaf, 0x7c, 0x7b, 0x6a, 0xea, 0xbf, 0x48,
  429. 0x14, 0xe7, 0x26, 0x56, 0xfa, 0xe8, 0xf2, 0xd2, 0x53, 0xd1, 0x08, 0x52, 0xa2, 0x6f,
  430. 0x55, 0xae, 0x93, 0xb5, 0x9b, 0x46, 0x91, 0x3d, 0xdf, 0x89, 0x1c, 0xb5, 0x38, 0x75,
  431. 0x5a, 0x45, 0x47, 0xde, 0x51, 0x12, 0x01, 0x5d, 0xc3, 0x00, 0x15, 0x7a, 0x1f, 0x37,
  432. 0xe7, 0x14, 0x28, 0xbc, 0x04, 0x75, 0xd9, 0x26, 0x8e, 0x4b, 0x53, 0x06, 0xd3, 0xa1,
  433. 0x22, 0x40, 0x13, 0xc4, 0x36, 0xbd, 0x1c, 0x23, 0xd7, 0x2a, 0x1c, 0x16, 0x46, 0x43,
  434. 0x50, 0x00, 0x07, 0x48, 0xc7, 0x7c, 0x80, 0xbd, 0x11, 0xee, 0x41, 0x20, 0xb3, 0x52,
  435. 0x3b, 0xd0, 0x0a, 0x2f, 0xdd, 0x02, 0xe8, 0xef, 0xfc, 0x7a, 0xfe, 0x3d, 0xd6, 0x73,
  436. 0x2c, 0x5d, 0xa0, 0x6b, 0x08, 0x98, 0x6c,
  437. ];
  438. // Need to explicity annotate the type here so that the compiler will use the default type
  439. // parameter.
  440. let msg: Message = Message::Transfer {
  441. amount: Amount([
  442. 0xfa, 0x22, 0x8b, 0x3d, 0xf3, 0x59, 0x21, 0xa1, 0xc9, 0x39, 0xad, 0x9c, 0x54, 0xe1,
  443. 0x2f, 0x87, 0xc6, 0x27, 0x25, 0xd1, 0xaf, 0x7c, 0x7b, 0x6a, 0xea, 0xbf, 0x48, 0x14,
  444. 0xe7, 0x26, 0x56, 0xfa,
  445. ]),
  446. token_address: Address([
  447. 0xe8, 0xf2, 0xd2, 0x53, 0xd1, 0x08, 0x52, 0xa2, 0x6f, 0x55, 0xae, 0x93, 0xb5, 0x9b,
  448. 0x46, 0x91, 0x3d, 0xdf, 0x89, 0x1c, 0xb5, 0x38, 0x75, 0x5a, 0x45, 0x47, 0xde, 0x51,
  449. 0x12, 0x01, 0x5d, 0xc3,
  450. ]),
  451. token_chain: Chain::Sui,
  452. recipient: Address([
  453. 0x7a, 0x1f, 0x37, 0xe7, 0x14, 0x28, 0xbc, 0x04, 0x75, 0xd9, 0x26, 0x8e, 0x4b, 0x53,
  454. 0x06, 0xd3, 0xa1, 0x22, 0x40, 0x13, 0xc4, 0x36, 0xbd, 0x1c, 0x23, 0xd7, 0x2a, 0x1c,
  455. 0x16, 0x46, 0x43, 0x50,
  456. ]),
  457. recipient_chain: Chain::Oasis,
  458. fee: Amount([
  459. 0x48, 0xc7, 0x7c, 0x80, 0xbd, 0x11, 0xee, 0x41, 0x20, 0xb3, 0x52, 0x3b, 0xd0, 0x0a,
  460. 0x2f, 0xdd, 0x02, 0xe8, 0xef, 0xfc, 0x7a, 0xfe, 0x3d, 0xd6, 0x73, 0x2c, 0x5d, 0xa0,
  461. 0x6b, 0x08, 0x98, 0x6c,
  462. ]),
  463. };
  464. assert_eq!(payload.as_ref(), &serde_wormhole::to_vec(&msg).unwrap());
  465. assert_eq!(msg, serde_wormhole::from_slice(&payload).unwrap());
  466. let encoded = serde_json::to_string(&msg).unwrap();
  467. assert_eq!(msg, serde_json::from_str(&encoded).unwrap());
  468. }
  469. #[test]
  470. pub fn asset_meta() {
  471. let payload = [
  472. 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  473. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  474. 0x00, 0xbe, 0xef, 0xfa, 0xce, 0x00, 0x02, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  475. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  476. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x45, 0x45, 0x46, 0x00, 0x00,
  477. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  478. 0x00, 0x42, 0x65, 0x65, 0x66, 0x20, 0x66, 0x61, 0x63, 0x65, 0x20, 0x54, 0x6f, 0x6b,
  479. 0x65, 0x6e,
  480. ];
  481. // Need to explicity annotate the type here so that the compiler will use the default type
  482. // parameter.
  483. let msg: Message = Message::AssetMeta {
  484. token_address: Address([
  485. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  486. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  487. 0xbe, 0xef, 0xfa, 0xce,
  488. ]),
  489. token_chain: Chain::Ethereum,
  490. decimals: 12,
  491. symbol: "BEEF".into(),
  492. name: "Beef face Token".into(),
  493. };
  494. assert_eq!(payload.as_ref(), &serde_wormhole::to_vec(&msg).unwrap());
  495. assert_eq!(msg, serde_wormhole::from_slice(&payload).unwrap());
  496. let encoded = serde_json::to_string(&msg).unwrap();
  497. assert_eq!(msg, serde_json::from_str(&encoded).unwrap());
  498. }
  499. #[test]
  500. pub fn transfer_with_payload() {
  501. let payload = [
  502. 0x03, 0x99, 0x30, 0x29, 0x01, 0x67, 0xf3, 0x48, 0x6a, 0xf6, 0x4c, 0xdd, 0x07, 0x64,
  503. 0xa1, 0x6a, 0xca, 0xcc, 0xc5, 0x64, 0x2a, 0x66, 0x71, 0xaa, 0x87, 0x98, 0x64, 0x0c,
  504. 0x25, 0x1f, 0x39, 0x73, 0x25, 0x12, 0x98, 0x15, 0xe5, 0x79, 0xdb, 0xd8, 0x25, 0xfd,
  505. 0x72, 0x58, 0x99, 0x97, 0xd1, 0x78, 0xb6, 0x2a, 0x57, 0x47, 0xab, 0xcf, 0x51, 0x62,
  506. 0xa5, 0xb7, 0xec, 0x19, 0x4e, 0x03, 0x51, 0x41, 0x18, 0x00, 0x08, 0xa4, 0x7e, 0xa2,
  507. 0x49, 0xd4, 0xf0, 0x56, 0x6f, 0xbd, 0x12, 0x77, 0xfe, 0xa8, 0x6e, 0x92, 0x81, 0x3a,
  508. 0x35, 0x90, 0x3b, 0x29, 0x73, 0x4d, 0x75, 0x56, 0x0a, 0xfe, 0x70, 0xb0, 0xb9, 0x10,
  509. 0x33, 0x00, 0x14, 0x47, 0x3e, 0x51, 0x74, 0x32, 0xbc, 0x3f, 0xb3, 0xf9, 0x82, 0xbb,
  510. 0xf3, 0xc9, 0x43, 0x41, 0xcf, 0x74, 0x24, 0xff, 0xa4, 0x02, 0x35, 0xbe, 0xb1, 0x7c,
  511. 0x47, 0x16, 0xba, 0xbc, 0xaa, 0xbe, 0x99, 0x54, 0xa2, 0x97, 0xbe, 0x2a, 0xed, 0xae,
  512. 0x91, 0x95, 0xb9, 0x6a, 0x8a, 0xba, 0xbd, 0x3a, 0xc1, 0xa4, 0xd1, 0x96, 0x0a, 0xf9,
  513. 0xab, 0x92, 0x42, 0x0d, 0x41, 0x33, 0xe5, 0xa8, 0x37, 0x32, 0xd3, 0xc3, 0xb8, 0xf3,
  514. 0x93, 0xd7, 0xc0, 0x9e, 0xe8, 0x87, 0xae, 0x16, 0xbf, 0xfa, 0x5e, 0x70, 0xea, 0x36,
  515. 0xa2, 0x82, 0x37, 0x1d, 0x46, 0x81, 0x94, 0x10, 0x34, 0xb1, 0xad, 0x0f, 0x4b, 0xc9,
  516. 0x17, 0x1e, 0x91, 0x25, 0x11,
  517. ];
  518. // No need to annotate the type here as the compiler can infer the generic parameter via the
  519. // `TransferWithPayload` variant.
  520. let msg = Message::TransferWithPayload {
  521. amount: Amount([
  522. 0x99, 0x30, 0x29, 0x01, 0x67, 0xf3, 0x48, 0x6a, 0xf6, 0x4c, 0xdd, 0x07, 0x64, 0xa1,
  523. 0x6a, 0xca, 0xcc, 0xc5, 0x64, 0x2a, 0x66, 0x71, 0xaa, 0x87, 0x98, 0x64, 0x0c, 0x25,
  524. 0x1f, 0x39, 0x73, 0x25,
  525. ]),
  526. token_address: Address([
  527. 0x12, 0x98, 0x15, 0xe5, 0x79, 0xdb, 0xd8, 0x25, 0xfd, 0x72, 0x58, 0x99, 0x97, 0xd1,
  528. 0x78, 0xb6, 0x2a, 0x57, 0x47, 0xab, 0xcf, 0x51, 0x62, 0xa5, 0xb7, 0xec, 0x19, 0x4e,
  529. 0x03, 0x51, 0x41, 0x18,
  530. ]),
  531. token_chain: Chain::Algorand,
  532. recipient: Address([
  533. 0xa4, 0x7e, 0xa2, 0x49, 0xd4, 0xf0, 0x56, 0x6f, 0xbd, 0x12, 0x77, 0xfe, 0xa8, 0x6e,
  534. 0x92, 0x81, 0x3a, 0x35, 0x90, 0x3b, 0x29, 0x73, 0x4d, 0x75, 0x56, 0x0a, 0xfe, 0x70,
  535. 0xb0, 0xb9, 0x10, 0x33,
  536. ]),
  537. recipient_chain: Chain::Osmosis,
  538. sender_address: Address([
  539. 0x47, 0x3e, 0x51, 0x74, 0x32, 0xbc, 0x3f, 0xb3, 0xf9, 0x82, 0xbb, 0xf3, 0xc9, 0x43,
  540. 0x41, 0xcf, 0x74, 0x24, 0xff, 0xa4, 0x02, 0x35, 0xbe, 0xb1, 0x7c, 0x47, 0x16, 0xba,
  541. 0xbc, 0xaa, 0xbe, 0x99,
  542. ]),
  543. payload: <Box<RawMessage>>::from(payload[133..].to_vec()),
  544. };
  545. assert_eq!(&payload[..], &serde_wormhole::to_vec(&msg).unwrap());
  546. assert_eq!(msg, serde_wormhole::from_slice(&payload).unwrap());
  547. let encoded = serde_json::to_vec(&msg).unwrap();
  548. assert_eq!(msg, serde_json::from_slice(&encoded).unwrap());
  549. }
  550. #[test]
  551. fn register_chain() {
  552. let buf = [
  553. 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xb0, 0x72, 0x50, 0x5b, 0x5b, 0x99, 0x9c,
  554. 0x1d, 0x08, 0x90, 0x5c, 0x02, 0xe2, 0xb6, 0xb2, 0x83, 0x2e, 0xf7, 0x2c, 0x0b, 0xa6,
  555. 0xc8, 0xdb, 0x4f, 0x77, 0xfe, 0x45, 0x7e, 0xf2, 0xb3, 0xd0, 0x53, 0x41, 0x0b, 0x1e,
  556. 0x92, 0xa9, 0x19, 0x4d, 0x92, 0x10, 0xdf, 0x24, 0xd9, 0x87, 0xac, 0x83, 0xd7, 0xb6,
  557. 0xf0, 0xc2, 0x1c, 0xe9, 0x0f, 0x8b, 0xc1, 0x86, 0x9d, 0xe0, 0x89, 0x8b, 0xda, 0x7e,
  558. 0x98, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00,
  559. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  560. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  561. 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01, 0x3c, 0x1b, 0xfa, 0x00, 0x00, 0x00, 0x00,
  562. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  563. 0x00, 0x00, 0x00, 0x00, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x42, 0x72, 0x69, 0x64, 0x67,
  564. 0x65, 0x01, 0x00, 0x00, 0x00, 0x01, 0x3b, 0x26, 0x40, 0x9f, 0x8a, 0xad, 0xed, 0x3f,
  565. 0x5d, 0xdc, 0xa1, 0x84, 0x69, 0x5a, 0xa6, 0xa0, 0xfa, 0x82, 0x9b, 0x0c, 0x85, 0xca,
  566. 0xf8, 0x48, 0x56, 0x32, 0x48, 0x96, 0xd2, 0x14, 0xca, 0x98,
  567. ];
  568. let vaa = Vaa {
  569. version: 1,
  570. guardian_set_index: 0,
  571. signatures: vec![Signature {
  572. index: 0,
  573. signature: [
  574. 0xb0, 0x72, 0x50, 0x5b, 0x5b, 0x99, 0x9c, 0x1d, 0x08, 0x90, 0x5c, 0x02, 0xe2,
  575. 0xb6, 0xb2, 0x83, 0x2e, 0xf7, 0x2c, 0x0b, 0xa6, 0xc8, 0xdb, 0x4f, 0x77, 0xfe,
  576. 0x45, 0x7e, 0xf2, 0xb3, 0xd0, 0x53, 0x41, 0x0b, 0x1e, 0x92, 0xa9, 0x19, 0x4d,
  577. 0x92, 0x10, 0xdf, 0x24, 0xd9, 0x87, 0xac, 0x83, 0xd7, 0xb6, 0xf0, 0xc2, 0x1c,
  578. 0xe9, 0x0f, 0x8b, 0xc1, 0x86, 0x9d, 0xe0, 0x89, 0x8b, 0xda, 0x7e, 0x98, 0x01,
  579. ],
  580. }],
  581. timestamp: 1,
  582. nonce: 1,
  583. emitter_chain: Chain::Solana,
  584. emitter_address: GOVERNANCE_EMITTER,
  585. sequence: 20_716_538,
  586. consistency_level: 0,
  587. payload: GovernancePacket {
  588. chain: Chain::Any,
  589. action: Action::RegisterChain {
  590. chain: Chain::Solana,
  591. emitter_address: Address([
  592. 0x3b, 0x26, 0x40, 0x9f, 0x8a, 0xad, 0xed, 0x3f, 0x5d, 0xdc, 0xa1, 0x84,
  593. 0x69, 0x5a, 0xa6, 0xa0, 0xfa, 0x82, 0x9b, 0x0c, 0x85, 0xca, 0xf8, 0x48,
  594. 0x56, 0x32, 0x48, 0x96, 0xd2, 0x14, 0xca, 0x98,
  595. ]),
  596. },
  597. },
  598. };
  599. assert_eq!(buf.as_ref(), &serde_wormhole::to_vec(&vaa).unwrap());
  600. assert_eq!(vaa, serde_wormhole::from_slice(&buf).unwrap());
  601. let encoded = serde_json::to_string(&vaa).unwrap();
  602. assert_eq!(vaa, serde_json::from_str(&encoded).unwrap());
  603. }
  604. #[test]
  605. fn contract_upgrade() {
  606. let buf = [
  607. 0x01, 0x00, 0x00, 0x00, 0x01, 0x0d, 0x02, 0x73, 0xaf, 0x3c, 0x2f, 0x55, 0x98, 0x90,
  608. 0x41, 0xb0, 0x06, 0x8a, 0x4e, 0xae, 0xba, 0x8f, 0x88, 0x25, 0x10, 0x60, 0x21, 0x99,
  609. 0x6d, 0xe6, 0x14, 0x39, 0x54, 0xc0, 0x6f, 0xc4, 0xcf, 0xad, 0x5c, 0x3f, 0x1a, 0xba,
  610. 0x6c, 0xa9, 0x51, 0x18, 0x8e, 0x96, 0x2f, 0x11, 0x25, 0x1c, 0x25, 0xca, 0x98, 0x62,
  611. 0x86, 0x85, 0xe2, 0xfc, 0x2b, 0x65, 0xec, 0x60, 0x94, 0x50, 0xcf, 0xc4, 0xe6, 0x51,
  612. 0x12, 0x00, 0x03, 0x00, 0xc6, 0x2e, 0xb0, 0xde, 0x7a, 0xb3, 0xd0, 0x28, 0x92, 0x0f,
  613. 0x18, 0xe1, 0x0d, 0xf7, 0xf2, 0xa0, 0x4d, 0x00, 0xeb, 0x88, 0xb8, 0x94, 0x0a, 0x27,
  614. 0xbb, 0xce, 0x8c, 0xe6, 0x6c, 0x67, 0x52, 0x68, 0x82, 0xc9, 0x6c, 0xc5, 0x0d, 0xd3,
  615. 0x81, 0xbd, 0xbf, 0xf3, 0x0b, 0xb6, 0x5b, 0x93, 0x47, 0xca, 0xdf, 0xf0, 0x96, 0x76,
  616. 0x72, 0x90, 0x43, 0xaf, 0x60, 0xd6, 0x52, 0xa0, 0xb9, 0x06, 0x30, 0x00, 0x04, 0xf0,
  617. 0x7b, 0x0f, 0xe6, 0xca, 0xb1, 0x8b, 0xe7, 0xae, 0x82, 0x7f, 0xe1, 0x1c, 0xa8, 0x99,
  618. 0x2f, 0xf0, 0xb5, 0xa2, 0xa3, 0x2d, 0x65, 0xbe, 0x95, 0x82, 0x31, 0xbf, 0x84, 0xcf,
  619. 0x6b, 0x14, 0xfb, 0x5e, 0xeb, 0x8a, 0x51, 0xad, 0xe1, 0xc7, 0x0a, 0xa5, 0xb8, 0xb8,
  620. 0xcf, 0x83, 0xaf, 0xe3, 0xc2, 0x2d, 0x34, 0x71, 0x48, 0x1b, 0xda, 0x38, 0x96, 0xea,
  621. 0x2a, 0x70, 0x46, 0x9f, 0x96, 0x92, 0xb8, 0x00, 0x05, 0x74, 0xd4, 0x96, 0x72, 0x9d,
  622. 0xde, 0x6e, 0x19, 0x09, 0x59, 0xa1, 0x79, 0x45, 0xe8, 0x7c, 0xd9, 0x5e, 0x23, 0xc1,
  623. 0x00, 0x47, 0xab, 0x2e, 0xef, 0x5c, 0x7d, 0x0e, 0xc6, 0xf9, 0x12, 0x08, 0xc7, 0x27,
  624. 0x9d, 0x8a, 0x1b, 0x1f, 0x4a, 0x60, 0x06, 0x9d, 0x25, 0x93, 0x2a, 0x67, 0xd6, 0x55,
  625. 0xf2, 0xd0, 0xb4, 0x20, 0x59, 0x00, 0x3d, 0xe7, 0x5f, 0xd3, 0xca, 0x79, 0x92, 0xfd,
  626. 0xd1, 0xb0, 0xd4, 0x01, 0x06, 0x51, 0xf0, 0x6a, 0xb6, 0xfd, 0xfd, 0x42, 0xf3, 0x23,
  627. 0x84, 0x0a, 0x81, 0x8b, 0x38, 0xcf, 0xd1, 0xc9, 0x9d, 0x22, 0x36, 0x6c, 0x87, 0x79,
  628. 0x03, 0xb9, 0x8d, 0xf4, 0x0b, 0xda, 0xf2, 0xa2, 0x04, 0x2e, 0xb8, 0xcd, 0x0e, 0x59,
  629. 0xc4, 0x63, 0x7e, 0x6a, 0x80, 0xa1, 0x99, 0xb1, 0x10, 0x8c, 0xd7, 0x65, 0x9b, 0xa8,
  630. 0x37, 0x0f, 0x6f, 0x94, 0x76, 0xb4, 0x79, 0x83, 0x98, 0x54, 0xd8, 0xc1, 0xa6, 0x00,
  631. 0x07, 0x78, 0x4b, 0x37, 0xc6, 0x10, 0x3c, 0x75, 0x2c, 0xd9, 0x7a, 0x58, 0x6b, 0xe8,
  632. 0xe1, 0xce, 0xff, 0x22, 0xa6, 0xe4, 0x88, 0x43, 0x32, 0x84, 0xff, 0x31, 0xcd, 0x90,
  633. 0x8b, 0x5c, 0x7d, 0x87, 0xe2, 0x44, 0xda, 0x75, 0x16, 0xd0, 0x7a, 0x0f, 0xa6, 0x92,
  634. 0x68, 0x4f, 0x82, 0x6e, 0x5e, 0x6c, 0x8b, 0x45, 0x20, 0x04, 0x20, 0x6d, 0x6f, 0xe5,
  635. 0xba, 0xe4, 0x6a, 0xfb, 0x1c, 0x21, 0x8c, 0xf5, 0x0d, 0x00, 0x09, 0x0b, 0x6c, 0xcc,
  636. 0xe6, 0x7e, 0xd5, 0x01, 0xcb, 0x20, 0xfb, 0x06, 0xde, 0x76, 0xb9, 0x08, 0x3f, 0x13,
  637. 0x29, 0xad, 0x78, 0xd3, 0x84, 0x51, 0x7a, 0x94, 0xab, 0x8e, 0x9a, 0xa6, 0x01, 0xbe,
  638. 0x7a, 0x0f, 0x00, 0xbb, 0x60, 0x3b, 0x36, 0x50, 0x4a, 0x74, 0xdd, 0xc3, 0x67, 0x35,
  639. 0x9c, 0x8e, 0xa0, 0x7f, 0x5c, 0xcd, 0x50, 0x22, 0x77, 0x2c, 0xc1, 0x57, 0xe0, 0x0f,
  640. 0x54, 0x15, 0x63, 0x71, 0xe4, 0x01, 0x0b, 0xe1, 0xe6, 0xb7, 0x12, 0xa2, 0x35, 0x3e,
  641. 0x49, 0x07, 0x92, 0x9c, 0x40, 0x57, 0xd5, 0xba, 0xbe, 0xf8, 0x0d, 0xc0, 0x9f, 0xeb,
  642. 0xb3, 0xdc, 0x29, 0x34, 0xf4, 0x40, 0x48, 0x79, 0x5e, 0xef, 0x95, 0x4e, 0x99, 0x10,
  643. 0x6c, 0xb2, 0x9b, 0x1a, 0x8d, 0x93, 0x53, 0x69, 0xda, 0xec, 0xbb, 0x8b, 0xae, 0x45,
  644. 0x19, 0x2e, 0xfc, 0x3c, 0xed, 0xbc, 0x57, 0x31, 0x5d, 0x67, 0xec, 0x9e, 0xa8, 0x00,
  645. 0x0a, 0x00, 0x0d, 0xdc, 0xc0, 0x4c, 0xd7, 0x55, 0x6a, 0x94, 0xe8, 0xb4, 0x18, 0xdc,
  646. 0x3a, 0x8a, 0x00, 0xef, 0xb1, 0x28, 0xd4, 0xf7, 0x6f, 0x71, 0x43, 0x12, 0x47, 0xa9,
  647. 0x2e, 0x7a, 0x19, 0xa8, 0x33, 0xfc, 0x02, 0x21, 0x5d, 0x1f, 0xd6, 0x9e, 0x0e, 0x59,
  648. 0x6d, 0xa5, 0x31, 0xea, 0x58, 0x7a, 0xe2, 0xac, 0x2f, 0x36, 0xd2, 0x0f, 0x3b, 0x19,
  649. 0x33, 0x06, 0x0a, 0xd6, 0xef, 0x3e, 0x9d, 0x7d, 0x84, 0x75, 0xba, 0x01, 0x0e, 0xc7,
  650. 0x62, 0x16, 0x49, 0x49, 0x06, 0xae, 0xd8, 0xd8, 0x31, 0x0c, 0x31, 0xa5, 0xe4, 0xa5,
  651. 0x45, 0xea, 0x2a, 0xf8, 0xdb, 0xe3, 0x8e, 0xeb, 0x74, 0xa3, 0xd1, 0x4f, 0x07, 0x34,
  652. 0xdd, 0x2b, 0x1a, 0x21, 0xb9, 0x85, 0x0e, 0xa2, 0x0e, 0x6c, 0x2c, 0xa4, 0x22, 0x48,
  653. 0x78, 0x8b, 0xfb, 0x17, 0x43, 0x9d, 0x37, 0xab, 0xda, 0x25, 0xd7, 0x05, 0xb5, 0x68,
  654. 0xb2, 0x65, 0xb1, 0x13, 0xb9, 0x76, 0xc5, 0x00, 0x10, 0xc6, 0x1f, 0xe6, 0xeb, 0xea,
  655. 0x61, 0xf2, 0xca, 0xe8, 0x95, 0xc3, 0x34, 0x96, 0x50, 0x70, 0x48, 0x7d, 0x39, 0xab,
  656. 0x6b, 0xf0, 0x44, 0x28, 0x34, 0x0a, 0xf0, 0xf7, 0x69, 0x9f, 0xdd, 0xd3, 0xc0, 0x1e,
  657. 0x0c, 0x86, 0xda, 0xea, 0x9e, 0xb4, 0x49, 0x70, 0x12, 0x48, 0xa2, 0x4f, 0xa4, 0xc0,
  658. 0xff, 0x75, 0xfb, 0x60, 0x0b, 0x2c, 0x01, 0x34, 0xbd, 0x72, 0x17, 0x91, 0xf6, 0x67,
  659. 0x11, 0x6e, 0x42, 0x00, 0x11, 0x19, 0xb7, 0x9c, 0xaa, 0x25, 0x0e, 0x75, 0xda, 0x14,
  660. 0x82, 0xc7, 0xf4, 0x12, 0x68, 0x73, 0x08, 0xd1, 0x3e, 0xf7, 0x00, 0xf7, 0x26, 0xb9,
  661. 0x94, 0x17, 0xbb, 0x75, 0xae, 0x6d, 0xd1, 0x43, 0xfc, 0x61, 0x9f, 0x8c, 0x9c, 0x29,
  662. 0xc7, 0x3f, 0x99, 0x49, 0xaf, 0xfd, 0x16, 0x29, 0xcc, 0x28, 0x6a, 0x61, 0x91, 0x7e,
  663. 0xd7, 0x85, 0x37, 0x54, 0xa4, 0x67, 0x02, 0x92, 0x0b, 0x76, 0xcf, 0x90, 0xeb, 0x00,
  664. 0x12, 0xb0, 0xba, 0xb5, 0xe1, 0xa8, 0xb3, 0x21, 0xe9, 0x2f, 0x9d, 0x3d, 0xf9, 0x24,
  665. 0x30, 0x18, 0x3e, 0x48, 0x43, 0xe5, 0x7c, 0x6f, 0x8c, 0x15, 0xc2, 0x2d, 0x62, 0xb2,
  666. 0xf8, 0xe4, 0xb8, 0xcd, 0xc2, 0x75, 0x9f, 0x28, 0x54, 0xb8, 0xd1, 0x22, 0xac, 0xdb,
  667. 0x4b, 0x4d, 0x89, 0x28, 0xb8, 0x7d, 0xf4, 0x19, 0x9c, 0xc6, 0x83, 0x01, 0x1d, 0x2e,
  668. 0x9b, 0x7d, 0x41, 0xa9, 0x6d, 0x8b, 0x48, 0x0c, 0xcc, 0x01, 0x00, 0x00, 0x00, 0x00,
  669. 0x39, 0xc4, 0xba, 0x76, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  670. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  671. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x25, 0x64, 0xd2, 0xef,
  672. 0xd6, 0x08, 0x4d, 0xf0, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  673. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x6f,
  674. 0x6b, 0x65, 0x6e, 0x42, 0x72, 0x69, 0x64, 0x67, 0x65, 0x02, 0x00, 0x03, 0x00, 0x00,
  675. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  676. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  677. 0x09, 0x83,
  678. ];
  679. let vaa = Vaa {
  680. version: 1,
  681. guardian_set_index: 1,
  682. signatures: vec![
  683. Signature {
  684. index: 2,
  685. signature: [
  686. 0x73, 0xaf, 0x3c, 0x2f, 0x55, 0x98, 0x90, 0x41, 0xb0, 0x06, 0x8a, 0x4e,
  687. 0xae, 0xba, 0x8f, 0x88, 0x25, 0x10, 0x60, 0x21, 0x99, 0x6d, 0xe6, 0x14,
  688. 0x39, 0x54, 0xc0, 0x6f, 0xc4, 0xcf, 0xad, 0x5c, 0x3f, 0x1a, 0xba, 0x6c,
  689. 0xa9, 0x51, 0x18, 0x8e, 0x96, 0x2f, 0x11, 0x25, 0x1c, 0x25, 0xca, 0x98,
  690. 0x62, 0x86, 0x85, 0xe2, 0xfc, 0x2b, 0x65, 0xec, 0x60, 0x94, 0x50, 0xcf,
  691. 0xc4, 0xe6, 0x51, 0x12, 0x00,
  692. ],
  693. },
  694. Signature {
  695. index: 3,
  696. signature: [
  697. 0x00, 0xc6, 0x2e, 0xb0, 0xde, 0x7a, 0xb3, 0xd0, 0x28, 0x92, 0x0f, 0x18,
  698. 0xe1, 0x0d, 0xf7, 0xf2, 0xa0, 0x4d, 0x00, 0xeb, 0x88, 0xb8, 0x94, 0x0a,
  699. 0x27, 0xbb, 0xce, 0x8c, 0xe6, 0x6c, 0x67, 0x52, 0x68, 0x82, 0xc9, 0x6c,
  700. 0xc5, 0x0d, 0xd3, 0x81, 0xbd, 0xbf, 0xf3, 0x0b, 0xb6, 0x5b, 0x93, 0x47,
  701. 0xca, 0xdf, 0xf0, 0x96, 0x76, 0x72, 0x90, 0x43, 0xaf, 0x60, 0xd6, 0x52,
  702. 0xa0, 0xb9, 0x06, 0x30, 0x00,
  703. ],
  704. },
  705. Signature {
  706. index: 4,
  707. signature: [
  708. 0xf0, 0x7b, 0x0f, 0xe6, 0xca, 0xb1, 0x8b, 0xe7, 0xae, 0x82, 0x7f, 0xe1,
  709. 0x1c, 0xa8, 0x99, 0x2f, 0xf0, 0xb5, 0xa2, 0xa3, 0x2d, 0x65, 0xbe, 0x95,
  710. 0x82, 0x31, 0xbf, 0x84, 0xcf, 0x6b, 0x14, 0xfb, 0x5e, 0xeb, 0x8a, 0x51,
  711. 0xad, 0xe1, 0xc7, 0x0a, 0xa5, 0xb8, 0xb8, 0xcf, 0x83, 0xaf, 0xe3, 0xc2,
  712. 0x2d, 0x34, 0x71, 0x48, 0x1b, 0xda, 0x38, 0x96, 0xea, 0x2a, 0x70, 0x46,
  713. 0x9f, 0x96, 0x92, 0xb8, 0x00,
  714. ],
  715. },
  716. Signature {
  717. index: 5,
  718. signature: [
  719. 0x74, 0xd4, 0x96, 0x72, 0x9d, 0xde, 0x6e, 0x19, 0x09, 0x59, 0xa1, 0x79,
  720. 0x45, 0xe8, 0x7c, 0xd9, 0x5e, 0x23, 0xc1, 0x00, 0x47, 0xab, 0x2e, 0xef,
  721. 0x5c, 0x7d, 0x0e, 0xc6, 0xf9, 0x12, 0x08, 0xc7, 0x27, 0x9d, 0x8a, 0x1b,
  722. 0x1f, 0x4a, 0x60, 0x06, 0x9d, 0x25, 0x93, 0x2a, 0x67, 0xd6, 0x55, 0xf2,
  723. 0xd0, 0xb4, 0x20, 0x59, 0x00, 0x3d, 0xe7, 0x5f, 0xd3, 0xca, 0x79, 0x92,
  724. 0xfd, 0xd1, 0xb0, 0xd4, 0x01,
  725. ],
  726. },
  727. Signature {
  728. index: 6,
  729. signature: [
  730. 0x51, 0xf0, 0x6a, 0xb6, 0xfd, 0xfd, 0x42, 0xf3, 0x23, 0x84, 0x0a, 0x81,
  731. 0x8b, 0x38, 0xcf, 0xd1, 0xc9, 0x9d, 0x22, 0x36, 0x6c, 0x87, 0x79, 0x03,
  732. 0xb9, 0x8d, 0xf4, 0x0b, 0xda, 0xf2, 0xa2, 0x04, 0x2e, 0xb8, 0xcd, 0x0e,
  733. 0x59, 0xc4, 0x63, 0x7e, 0x6a, 0x80, 0xa1, 0x99, 0xb1, 0x10, 0x8c, 0xd7,
  734. 0x65, 0x9b, 0xa8, 0x37, 0x0f, 0x6f, 0x94, 0x76, 0xb4, 0x79, 0x83, 0x98,
  735. 0x54, 0xd8, 0xc1, 0xa6, 0x00,
  736. ],
  737. },
  738. Signature {
  739. index: 7,
  740. signature: [
  741. 0x78, 0x4b, 0x37, 0xc6, 0x10, 0x3c, 0x75, 0x2c, 0xd9, 0x7a, 0x58, 0x6b,
  742. 0xe8, 0xe1, 0xce, 0xff, 0x22, 0xa6, 0xe4, 0x88, 0x43, 0x32, 0x84, 0xff,
  743. 0x31, 0xcd, 0x90, 0x8b, 0x5c, 0x7d, 0x87, 0xe2, 0x44, 0xda, 0x75, 0x16,
  744. 0xd0, 0x7a, 0x0f, 0xa6, 0x92, 0x68, 0x4f, 0x82, 0x6e, 0x5e, 0x6c, 0x8b,
  745. 0x45, 0x20, 0x04, 0x20, 0x6d, 0x6f, 0xe5, 0xba, 0xe4, 0x6a, 0xfb, 0x1c,
  746. 0x21, 0x8c, 0xf5, 0x0d, 0x00,
  747. ],
  748. },
  749. Signature {
  750. index: 9,
  751. signature: [
  752. 0x0b, 0x6c, 0xcc, 0xe6, 0x7e, 0xd5, 0x01, 0xcb, 0x20, 0xfb, 0x06, 0xde,
  753. 0x76, 0xb9, 0x08, 0x3f, 0x13, 0x29, 0xad, 0x78, 0xd3, 0x84, 0x51, 0x7a,
  754. 0x94, 0xab, 0x8e, 0x9a, 0xa6, 0x01, 0xbe, 0x7a, 0x0f, 0x00, 0xbb, 0x60,
  755. 0x3b, 0x36, 0x50, 0x4a, 0x74, 0xdd, 0xc3, 0x67, 0x35, 0x9c, 0x8e, 0xa0,
  756. 0x7f, 0x5c, 0xcd, 0x50, 0x22, 0x77, 0x2c, 0xc1, 0x57, 0xe0, 0x0f, 0x54,
  757. 0x15, 0x63, 0x71, 0xe4, 0x01,
  758. ],
  759. },
  760. Signature {
  761. index: 11,
  762. signature: [
  763. 0xe1, 0xe6, 0xb7, 0x12, 0xa2, 0x35, 0x3e, 0x49, 0x07, 0x92, 0x9c, 0x40,
  764. 0x57, 0xd5, 0xba, 0xbe, 0xf8, 0x0d, 0xc0, 0x9f, 0xeb, 0xb3, 0xdc, 0x29,
  765. 0x34, 0xf4, 0x40, 0x48, 0x79, 0x5e, 0xef, 0x95, 0x4e, 0x99, 0x10, 0x6c,
  766. 0xb2, 0x9b, 0x1a, 0x8d, 0x93, 0x53, 0x69, 0xda, 0xec, 0xbb, 0x8b, 0xae,
  767. 0x45, 0x19, 0x2e, 0xfc, 0x3c, 0xed, 0xbc, 0x57, 0x31, 0x5d, 0x67, 0xec,
  768. 0x9e, 0xa8, 0x00, 0x0a, 0x00,
  769. ],
  770. },
  771. Signature {
  772. index: 13,
  773. signature: [
  774. 0xdc, 0xc0, 0x4c, 0xd7, 0x55, 0x6a, 0x94, 0xe8, 0xb4, 0x18, 0xdc, 0x3a,
  775. 0x8a, 0x00, 0xef, 0xb1, 0x28, 0xd4, 0xf7, 0x6f, 0x71, 0x43, 0x12, 0x47,
  776. 0xa9, 0x2e, 0x7a, 0x19, 0xa8, 0x33, 0xfc, 0x02, 0x21, 0x5d, 0x1f, 0xd6,
  777. 0x9e, 0x0e, 0x59, 0x6d, 0xa5, 0x31, 0xea, 0x58, 0x7a, 0xe2, 0xac, 0x2f,
  778. 0x36, 0xd2, 0x0f, 0x3b, 0x19, 0x33, 0x06, 0x0a, 0xd6, 0xef, 0x3e, 0x9d,
  779. 0x7d, 0x84, 0x75, 0xba, 0x01,
  780. ],
  781. },
  782. Signature {
  783. index: 14,
  784. signature: [
  785. 0xc7, 0x62, 0x16, 0x49, 0x49, 0x06, 0xae, 0xd8, 0xd8, 0x31, 0x0c, 0x31,
  786. 0xa5, 0xe4, 0xa5, 0x45, 0xea, 0x2a, 0xf8, 0xdb, 0xe3, 0x8e, 0xeb, 0x74,
  787. 0xa3, 0xd1, 0x4f, 0x07, 0x34, 0xdd, 0x2b, 0x1a, 0x21, 0xb9, 0x85, 0x0e,
  788. 0xa2, 0x0e, 0x6c, 0x2c, 0xa4, 0x22, 0x48, 0x78, 0x8b, 0xfb, 0x17, 0x43,
  789. 0x9d, 0x37, 0xab, 0xda, 0x25, 0xd7, 0x05, 0xb5, 0x68, 0xb2, 0x65, 0xb1,
  790. 0x13, 0xb9, 0x76, 0xc5, 0x00,
  791. ],
  792. },
  793. Signature {
  794. index: 16,
  795. signature: [
  796. 0xc6, 0x1f, 0xe6, 0xeb, 0xea, 0x61, 0xf2, 0xca, 0xe8, 0x95, 0xc3, 0x34,
  797. 0x96, 0x50, 0x70, 0x48, 0x7d, 0x39, 0xab, 0x6b, 0xf0, 0x44, 0x28, 0x34,
  798. 0x0a, 0xf0, 0xf7, 0x69, 0x9f, 0xdd, 0xd3, 0xc0, 0x1e, 0x0c, 0x86, 0xda,
  799. 0xea, 0x9e, 0xb4, 0x49, 0x70, 0x12, 0x48, 0xa2, 0x4f, 0xa4, 0xc0, 0xff,
  800. 0x75, 0xfb, 0x60, 0x0b, 0x2c, 0x01, 0x34, 0xbd, 0x72, 0x17, 0x91, 0xf6,
  801. 0x67, 0x11, 0x6e, 0x42, 0x00,
  802. ],
  803. },
  804. Signature {
  805. index: 17,
  806. signature: [
  807. 0x19, 0xb7, 0x9c, 0xaa, 0x25, 0x0e, 0x75, 0xda, 0x14, 0x82, 0xc7, 0xf4,
  808. 0x12, 0x68, 0x73, 0x08, 0xd1, 0x3e, 0xf7, 0x00, 0xf7, 0x26, 0xb9, 0x94,
  809. 0x17, 0xbb, 0x75, 0xae, 0x6d, 0xd1, 0x43, 0xfc, 0x61, 0x9f, 0x8c, 0x9c,
  810. 0x29, 0xc7, 0x3f, 0x99, 0x49, 0xaf, 0xfd, 0x16, 0x29, 0xcc, 0x28, 0x6a,
  811. 0x61, 0x91, 0x7e, 0xd7, 0x85, 0x37, 0x54, 0xa4, 0x67, 0x02, 0x92, 0x0b,
  812. 0x76, 0xcf, 0x90, 0xeb, 0x00,
  813. ],
  814. },
  815. Signature {
  816. index: 18,
  817. signature: [
  818. 0xb0, 0xba, 0xb5, 0xe1, 0xa8, 0xb3, 0x21, 0xe9, 0x2f, 0x9d, 0x3d, 0xf9,
  819. 0x24, 0x30, 0x18, 0x3e, 0x48, 0x43, 0xe5, 0x7c, 0x6f, 0x8c, 0x15, 0xc2,
  820. 0x2d, 0x62, 0xb2, 0xf8, 0xe4, 0xb8, 0xcd, 0xc2, 0x75, 0x9f, 0x28, 0x54,
  821. 0xb8, 0xd1, 0x22, 0xac, 0xdb, 0x4b, 0x4d, 0x89, 0x28, 0xb8, 0x7d, 0xf4,
  822. 0x19, 0x9c, 0xc6, 0x83, 0x01, 0x1d, 0x2e, 0x9b, 0x7d, 0x41, 0xa9, 0x6d,
  823. 0x8b, 0x48, 0x0c, 0xcc, 0x01,
  824. ],
  825. },
  826. ],
  827. timestamp: 0,
  828. nonce: 969_194_102,
  829. emitter_chain: Chain::Solana,
  830. emitter_address: GOVERNANCE_EMITTER,
  831. sequence: 2_694_510_404_604_284_400,
  832. consistency_level: 32,
  833. payload: GovernancePacket {
  834. chain: Chain::Terra,
  835. action: Action::ContractUpgrade {
  836. new_contract: Address([
  837. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  838. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  839. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x83,
  840. ]),
  841. },
  842. },
  843. };
  844. assert_eq!(buf.as_ref(), &serde_wormhole::to_vec(&vaa).unwrap());
  845. assert_eq!(vaa, serde_wormhole::from_slice(&buf).unwrap());
  846. let encoded = serde_json::to_string(&vaa).unwrap();
  847. assert_eq!(vaa, serde_json::from_str(&encoded).unwrap());
  848. }
  849. }