integration.rs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631
  1. #![allow(warnings)]
  2. use borsh::BorshSerialize;
  3. use byteorder::{
  4. BigEndian,
  5. WriteBytesExt,
  6. };
  7. use hex_literal::hex;
  8. use rand::Rng;
  9. use secp256k1::{
  10. Message as Secp256k1Message,
  11. PublicKey,
  12. SecretKey,
  13. };
  14. use sha3::Digest;
  15. use solana_client::rpc_client::RpcClient;
  16. use solana_program::{
  17. borsh::try_from_slice_unchecked,
  18. hash,
  19. instruction::{
  20. AccountMeta,
  21. Instruction,
  22. },
  23. program_pack::Pack,
  24. pubkey::Pubkey,
  25. system_instruction::{
  26. self,
  27. create_account,
  28. },
  29. system_program,
  30. sysvar,
  31. };
  32. use solana_sdk::{
  33. commitment_config::CommitmentConfig,
  34. signature::{
  35. read_keypair_file,
  36. Keypair,
  37. Signer,
  38. },
  39. transaction::Transaction,
  40. };
  41. use solitaire::{
  42. processors::seeded::Seeded,
  43. AccountState,
  44. };
  45. use spl_token::state::Mint;
  46. use std::{
  47. convert::TryInto,
  48. io::{
  49. Cursor,
  50. Write,
  51. },
  52. time::{
  53. Duration,
  54. SystemTime,
  55. },
  56. };
  57. use bridge::{
  58. accounts::{
  59. Bridge,
  60. FeeCollector,
  61. GuardianSet,
  62. GuardianSetDerivationData,
  63. PostedVAA,
  64. PostedVAADerivationData,
  65. SignatureSet,
  66. },
  67. instruction,
  68. types::{
  69. BridgeConfig,
  70. BridgeData,
  71. GovernancePayloadGuardianSetChange,
  72. GovernancePayloadSetMessageFee,
  73. GovernancePayloadTransferFees,
  74. GuardianSetData,
  75. MessageData,
  76. PostedVAAData,
  77. SequenceTracker,
  78. SignatureSet as SignatureSetData,
  79. },
  80. Initialize,
  81. PostVAA,
  82. PostVAAData,
  83. SerializePayload,
  84. Signature,
  85. };
  86. use primitive_types::U256;
  87. use std::{
  88. collections::HashMap,
  89. str::FromStr,
  90. time::UNIX_EPOCH,
  91. };
  92. use token_bridge::{
  93. accounts::{
  94. EmitterAccount,
  95. WrappedDerivationData,
  96. WrappedMint,
  97. },
  98. messages::{
  99. PayloadAssetMeta,
  100. PayloadGovernanceRegisterChain,
  101. PayloadTransfer,
  102. },
  103. types::Address,
  104. };
  105. mod common;
  106. const GOVERNANCE_KEY: [u8; 64] = [
  107. 240, 133, 120, 113, 30, 67, 38, 184, 197, 72, 234, 99, 241, 21, 58, 225, 41, 157, 171, 44, 196,
  108. 163, 134, 236, 92, 148, 110, 68, 127, 114, 177, 0, 173, 253, 199, 9, 242, 142, 201, 174, 108,
  109. 197, 18, 102, 115, 0, 31, 205, 127, 188, 191, 56, 171, 228, 20, 247, 149, 170, 141, 231, 147,
  110. 88, 97, 199,
  111. ];
  112. struct Context {
  113. /// Address of the core bridge contract.
  114. bridge: Pubkey,
  115. /// Shared RPC client for tests to make transactions with.
  116. client: RpcClient,
  117. /// Payer key with a ton of lamports to ease testing with.
  118. payer: Keypair,
  119. /// Track nonces throughout the tests.
  120. seq: Sequencer,
  121. /// Address of the token bridge itself that we wish to test.
  122. token_bridge: Pubkey,
  123. /// Keypairs for mint information, required in multiple tests.
  124. mint_authority: Keypair,
  125. mint: Keypair,
  126. mint_meta: Pubkey,
  127. /// Keypairs for test token accounts.
  128. token_authority: Keypair,
  129. token_account: Keypair,
  130. metadata_account: Pubkey,
  131. }
  132. /// Small helper to track and provide sequences during tests. This is in particular needed for
  133. /// guardian operations that require them for derivations.
  134. struct Sequencer {
  135. sequences: HashMap<[u8; 32], u64>,
  136. }
  137. impl Sequencer {
  138. fn next(&mut self, emitter: [u8; 32]) -> u64 {
  139. let entry = self.sequences.entry(emitter).or_insert(0);
  140. *entry += 1;
  141. *entry - 1
  142. }
  143. fn peek(&mut self, emitter: [u8; 32]) -> u64 {
  144. *self.sequences.entry(emitter).or_insert(0)
  145. }
  146. }
  147. #[test]
  148. fn run_integration_tests() {
  149. let (payer, client, bridge, token_bridge) = common::setup();
  150. // Setup a Bridge to test against.
  151. println!("Bridge: {}", bridge);
  152. common::initialize_bridge(&client, &bridge, &payer);
  153. // Context for test environment.
  154. let mint = Keypair::new();
  155. let mint_pubkey = mint.pubkey();
  156. let metadata_pubkey = Pubkey::from_str("metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s").unwrap();
  157. // SPL Token Meta
  158. let metadata_seeds = &[
  159. "metadata".as_bytes(),
  160. metadata_pubkey.as_ref(),
  161. mint_pubkey.as_ref(),
  162. ];
  163. let (metadata_key, metadata_bump_seed) = Pubkey::find_program_address(
  164. metadata_seeds,
  165. &Pubkey::from_str("metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s").unwrap(),
  166. );
  167. // Token Bridge Meta
  168. use token_bridge::accounts::WrappedTokenMeta;
  169. let metadata_account = WrappedTokenMeta::<'_, { AccountState::Uninitialized }>::key(
  170. &token_bridge::accounts::WrappedMetaDerivationData {
  171. mint_key: mint_pubkey.clone(),
  172. },
  173. &token_bridge,
  174. );
  175. let mut context = Context {
  176. seq: Sequencer {
  177. sequences: HashMap::new(),
  178. },
  179. bridge,
  180. client,
  181. payer,
  182. token_bridge,
  183. mint_authority: Keypair::new(),
  184. mint,
  185. mint_meta: metadata_account,
  186. token_account: Keypair::new(),
  187. token_authority: Keypair::new(),
  188. metadata_account: metadata_key,
  189. };
  190. // Create a mint for use within tests.
  191. common::create_mint(
  192. &context.client,
  193. &context.payer,
  194. &context.mint_authority.pubkey(),
  195. &context.mint,
  196. )
  197. .unwrap();
  198. // Create Token accounts for use within tests.
  199. common::create_token_account(
  200. &context.client,
  201. &context.payer,
  202. &context.token_account,
  203. context.token_authority.pubkey(),
  204. context.mint.pubkey(),
  205. )
  206. .unwrap();
  207. // Mint tokens
  208. common::mint_tokens(
  209. &context.client,
  210. &context.payer,
  211. &context.mint_authority,
  212. &context.mint,
  213. &context.token_account.pubkey(),
  214. 1000,
  215. )
  216. .unwrap();
  217. // Initialize the bridge and verify the bridges state.
  218. test_initialize(&mut context);
  219. test_transfer_native(&mut context);
  220. test_attest(&mut context);
  221. test_register_chain(&mut context);
  222. test_transfer_native_in(&mut context);
  223. // Create an SPL Metadata account to test attestations for wrapped tokens.
  224. common::create_spl_metadata(
  225. &context.client,
  226. &context.payer,
  227. &context.metadata_account,
  228. &context.mint_authority,
  229. &context.mint,
  230. &context.payer.pubkey(),
  231. "BTC".to_string(),
  232. "Bitcoin".to_string(),
  233. )
  234. .unwrap();
  235. let wrapped = test_create_wrapped(&mut context);
  236. let wrapped_acc = Keypair::new();
  237. common::create_token_account(
  238. &context.client,
  239. &context.payer,
  240. &wrapped_acc,
  241. context.token_authority.pubkey(),
  242. wrapped,
  243. )
  244. .unwrap();
  245. test_transfer_wrapped_in(&mut context, wrapped_acc.pubkey());
  246. test_transfer_wrapped(&mut context, wrapped_acc.pubkey());
  247. }
  248. fn test_attest(context: &mut Context) -> () {
  249. println!("Attest");
  250. use token_bridge::{
  251. accounts::ConfigAccount,
  252. types::Config,
  253. };
  254. let Context {
  255. ref payer,
  256. ref client,
  257. ref bridge,
  258. ref token_bridge,
  259. ref mint_authority,
  260. ref mint,
  261. ref mint_meta,
  262. ref metadata_account,
  263. ..
  264. } = context;
  265. let message = &Keypair::new();
  266. common::attest(
  267. client,
  268. token_bridge,
  269. bridge,
  270. payer,
  271. message,
  272. mint.pubkey(),
  273. 0,
  274. )
  275. .unwrap();
  276. let emitter_key = EmitterAccount::key(None, &token_bridge);
  277. let mint_data = Mint::unpack(
  278. &client
  279. .get_account_with_commitment(&mint.pubkey(), CommitmentConfig::processed())
  280. .unwrap()
  281. .value
  282. .unwrap()
  283. .data,
  284. )
  285. .unwrap();
  286. let payload = PayloadAssetMeta {
  287. token_address: mint.pubkey().to_bytes(),
  288. token_chain: 1,
  289. decimals: mint_data.decimals,
  290. symbol: "USD".to_string(),
  291. name: "Bitcoin".to_string(),
  292. };
  293. let payload = payload.try_to_vec().unwrap();
  294. }
  295. fn test_transfer_native(context: &mut Context) -> () {
  296. println!("Transfer Native");
  297. use token_bridge::{
  298. accounts::ConfigAccount,
  299. types::Config,
  300. };
  301. let Context {
  302. ref payer,
  303. ref client,
  304. ref bridge,
  305. ref token_bridge,
  306. ref mint_authority,
  307. ref mint,
  308. ref mint_meta,
  309. ref token_account,
  310. ref token_authority,
  311. ..
  312. } = context;
  313. let message = &Keypair::new();
  314. common::transfer_native(
  315. client,
  316. token_bridge,
  317. bridge,
  318. payer,
  319. message,
  320. token_account,
  321. token_authority,
  322. mint.pubkey(),
  323. 100,
  324. )
  325. .unwrap();
  326. }
  327. fn test_transfer_wrapped(context: &mut Context, token_account: Pubkey) -> () {
  328. println!("TransferWrapped");
  329. use token_bridge::{
  330. accounts::ConfigAccount,
  331. types::Config,
  332. };
  333. let Context {
  334. ref payer,
  335. ref client,
  336. ref bridge,
  337. ref token_bridge,
  338. ref mint_authority,
  339. ref token_authority,
  340. ..
  341. } = context;
  342. let message = &Keypair::new();
  343. common::transfer_wrapped(
  344. client,
  345. token_bridge,
  346. bridge,
  347. payer,
  348. message,
  349. token_account,
  350. token_authority,
  351. 2,
  352. [1u8; 32],
  353. 10000000,
  354. )
  355. .unwrap();
  356. }
  357. fn test_register_chain(context: &mut Context) -> () {
  358. println!("Register Chain");
  359. use token_bridge::{
  360. accounts::ConfigAccount,
  361. types::Config,
  362. };
  363. let Context {
  364. ref payer,
  365. ref client,
  366. ref bridge,
  367. ref token_bridge,
  368. ref mint_authority,
  369. ref mint,
  370. ref mint_meta,
  371. ref token_account,
  372. ref token_authority,
  373. ..
  374. } = context;
  375. let nonce = rand::thread_rng().gen();
  376. let emitter = Keypair::from_bytes(&GOVERNANCE_KEY).unwrap();
  377. let payload = PayloadGovernanceRegisterChain {
  378. chain: 2,
  379. endpoint_address: [0u8; 32],
  380. };
  381. let message = payload.try_to_vec().unwrap();
  382. let (vaa, _, _) = common::generate_vaa(emitter.pubkey().to_bytes(), 1, message, nonce, 0);
  383. common::post_vaa(client, bridge, payer, vaa.clone()).unwrap();
  384. let mut msg_derivation_data = &PostedVAADerivationData {
  385. payload_hash: bridge::instructions::hash_vaa(&vaa).to_vec(),
  386. };
  387. let message_key =
  388. PostedVAA::<'_, { AccountState::MaybeInitialized }>::key(&msg_derivation_data, &bridge);
  389. common::register_chain(
  390. client,
  391. token_bridge,
  392. bridge,
  393. &message_key,
  394. vaa,
  395. payload,
  396. payer,
  397. )
  398. .unwrap();
  399. }
  400. fn test_transfer_native_in(context: &mut Context) -> () {
  401. println!("TransferNativeIn");
  402. use token_bridge::{
  403. accounts::ConfigAccount,
  404. types::Config,
  405. };
  406. let Context {
  407. ref payer,
  408. ref client,
  409. ref bridge,
  410. ref token_bridge,
  411. ref mint_authority,
  412. ref mint,
  413. ref mint_meta,
  414. ref token_account,
  415. ref token_authority,
  416. ..
  417. } = context;
  418. let nonce = rand::thread_rng().gen();
  419. let payload = PayloadTransfer {
  420. amount: U256::from(100),
  421. token_address: mint.pubkey().to_bytes(),
  422. token_chain: 1,
  423. to: token_account.pubkey().to_bytes(),
  424. to_chain: 1,
  425. fee: U256::from(0),
  426. };
  427. let message = payload.try_to_vec().unwrap();
  428. let (vaa, _, _) = common::generate_vaa([0u8; 32], 2, message, nonce, 1);
  429. common::post_vaa(client, bridge, payer, vaa.clone()).unwrap();
  430. let mut msg_derivation_data = &PostedVAADerivationData {
  431. payload_hash: bridge::instructions::hash_vaa(&vaa).to_vec(),
  432. };
  433. let message_key =
  434. PostedVAA::<'_, { AccountState::MaybeInitialized }>::key(&msg_derivation_data, &bridge);
  435. common::complete_native(
  436. client,
  437. token_bridge,
  438. bridge,
  439. &message_key,
  440. vaa,
  441. payload,
  442. payer,
  443. )
  444. .unwrap();
  445. }
  446. fn test_transfer_wrapped_in(context: &mut Context, to: Pubkey) -> () {
  447. println!("TransferWrappedIn");
  448. use token_bridge::{
  449. accounts::ConfigAccount,
  450. types::Config,
  451. };
  452. let Context {
  453. ref payer,
  454. ref client,
  455. ref bridge,
  456. ref token_bridge,
  457. ref mint_authority,
  458. ref mint,
  459. ref mint_meta,
  460. ref token_account,
  461. ref token_authority,
  462. ..
  463. } = context;
  464. let nonce = rand::thread_rng().gen();
  465. let payload = PayloadTransfer {
  466. amount: U256::from(100000000),
  467. token_address: [1u8; 32],
  468. token_chain: 2,
  469. to: to.to_bytes(),
  470. to_chain: 1,
  471. fee: U256::from(0),
  472. };
  473. let message = payload.try_to_vec().unwrap();
  474. let (vaa, _, _) = common::generate_vaa([0u8; 32], 2, message, nonce, rand::thread_rng().gen());
  475. common::post_vaa(client, bridge, payer, vaa.clone()).unwrap();
  476. let mut msg_derivation_data = &PostedVAADerivationData {
  477. payload_hash: bridge::instructions::hash_vaa(&vaa).to_vec(),
  478. };
  479. let message_key =
  480. PostedVAA::<'_, { AccountState::MaybeInitialized }>::key(&msg_derivation_data, &bridge);
  481. common::complete_transfer_wrapped(
  482. client,
  483. token_bridge,
  484. bridge,
  485. &message_key,
  486. vaa,
  487. payload,
  488. payer,
  489. )
  490. .unwrap();
  491. }
  492. fn test_create_wrapped(context: &mut Context) -> (Pubkey) {
  493. println!("CreateWrapped");
  494. use token_bridge::{
  495. accounts::ConfigAccount,
  496. types::Config,
  497. };
  498. let Context {
  499. ref payer,
  500. ref client,
  501. ref bridge,
  502. ref token_bridge,
  503. ref mint_authority,
  504. ref mint,
  505. ref mint_meta,
  506. ref token_account,
  507. ref token_authority,
  508. ..
  509. } = context;
  510. let nonce = rand::thread_rng().gen();
  511. let payload = PayloadAssetMeta {
  512. token_address: [1u8; 32],
  513. token_chain: 2,
  514. decimals: 7,
  515. symbol: "".to_string(),
  516. name: "".to_string(),
  517. };
  518. let message = payload.try_to_vec().unwrap();
  519. let (vaa, _, _) = common::generate_vaa([0u8; 32], 2, message, nonce, 2);
  520. common::post_vaa(client, bridge, payer, vaa.clone()).unwrap();
  521. let mut msg_derivation_data = &PostedVAADerivationData {
  522. payload_hash: bridge::instructions::hash_vaa(&vaa).to_vec(),
  523. };
  524. let message_key =
  525. PostedVAA::<'_, { AccountState::MaybeInitialized }>::key(&msg_derivation_data, &bridge);
  526. common::create_wrapped(
  527. client,
  528. token_bridge,
  529. bridge,
  530. &message_key,
  531. vaa,
  532. payload,
  533. payer,
  534. )
  535. .unwrap();
  536. return WrappedMint::<'_, { AccountState::Initialized }>::key(
  537. &WrappedDerivationData {
  538. token_chain: 2,
  539. token_address: [1u8; 32],
  540. },
  541. token_bridge,
  542. );
  543. }
  544. fn test_initialize(context: &mut Context) {
  545. println!("Initialize");
  546. use token_bridge::{
  547. accounts::ConfigAccount,
  548. types::Config,
  549. };
  550. let Context {
  551. ref payer,
  552. ref client,
  553. ref bridge,
  554. ref token_bridge,
  555. ..
  556. } = context;
  557. common::initialize(client, token_bridge, payer, &bridge).unwrap();
  558. // Verify Token Bridge State
  559. let config_key = ConfigAccount::<'_, { AccountState::Uninitialized }>::key(None, &token_bridge);
  560. let config: Config = common::get_account_data(client, &config_key).unwrap();
  561. assert_eq!(config.wormhole_bridge, *bridge);
  562. }