withdraw_excess_lamports.rs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756
  1. mod setup;
  2. use assert_matches::assert_matches;
  3. use setup::{mint, TOKEN_PROGRAM_ID};
  4. use solana_program_test::{tokio, BanksClientError, ProgramTest};
  5. use solana_sdk::{
  6. instruction::InstructionError,
  7. pubkey::Pubkey,
  8. signature::{Keypair, Signer},
  9. system_instruction,
  10. transaction::{Transaction, TransactionError},
  11. };
  12. use spl_token_interface::state::{account::Account, mint::Mint, multisig::Multisig};
  13. use std::mem::size_of;
  14. #[test_case::test_case(TOKEN_PROGRAM_ID ; "p-token")]
  15. #[tokio::test]
  16. async fn withdraw_excess_lamports_from_mint(token_program: Pubkey) {
  17. let context = ProgramTest::new("pinocchio_token_program", TOKEN_PROGRAM_ID, None)
  18. .start_with_context()
  19. .await;
  20. let excess_lamports = 4_000_000_000_000;
  21. // Given a mint authority, freeze authority and an account keypair.
  22. let mint_authority = Keypair::new();
  23. let freeze_authority = Pubkey::new_unique();
  24. let account = Keypair::new();
  25. let account_pubkey = account.pubkey();
  26. let account_size = size_of::<Mint>();
  27. let rent = context.banks_client.get_rent().await.unwrap();
  28. let mut initialize_ix = spl_token::instruction::initialize_mint(
  29. &spl_token::ID,
  30. &account.pubkey(),
  31. &mint_authority.pubkey(),
  32. Some(&freeze_authority),
  33. 0,
  34. )
  35. .unwrap();
  36. // Switches the program id to the token program.
  37. initialize_ix.program_id = token_program;
  38. // And we initialize a mint account with excess lamports.
  39. let instructions = vec![
  40. system_instruction::create_account(
  41. &context.payer.pubkey(),
  42. &account.pubkey(),
  43. rent.minimum_balance(account_size) + excess_lamports,
  44. account_size as u64,
  45. &token_program,
  46. ),
  47. initialize_ix,
  48. ];
  49. let tx = Transaction::new_signed_with_payer(
  50. &instructions,
  51. Some(&context.payer.pubkey()),
  52. &[&context.payer, &account],
  53. context.last_blockhash,
  54. );
  55. context.banks_client.process_transaction(tx).await.unwrap();
  56. let account = context
  57. .banks_client
  58. .get_account(account.pubkey())
  59. .await
  60. .unwrap();
  61. assert!(account.is_some());
  62. let account = account.unwrap();
  63. assert_eq!(
  64. account.lamports,
  65. rent.minimum_balance(account_size) + excess_lamports
  66. );
  67. // When we withdraw the excess lamports.
  68. let destination = Pubkey::new_unique();
  69. let mut withdraw_ix = spl_token_2022::instruction::withdraw_excess_lamports(
  70. &spl_token_2022::ID,
  71. &account_pubkey,
  72. &destination,
  73. &mint_authority.pubkey(),
  74. &[],
  75. )
  76. .unwrap();
  77. // Switches the program id to the token program.
  78. withdraw_ix.program_id = token_program;
  79. let tx = Transaction::new_signed_with_payer(
  80. &[withdraw_ix],
  81. Some(&context.payer.pubkey()),
  82. &[&context.payer, &mint_authority],
  83. context.last_blockhash,
  84. );
  85. context.banks_client.process_transaction(tx).await.unwrap();
  86. // Then the destination account has the excess lamports.
  87. let destination = context.banks_client.get_account(destination).await.unwrap();
  88. assert!(destination.is_some());
  89. let destination = destination.unwrap();
  90. assert_eq!(destination.lamports, excess_lamports);
  91. }
  92. #[test_case::test_case(TOKEN_PROGRAM_ID ; "p-token")]
  93. #[tokio::test]
  94. async fn withdraw_excess_lamports_from_account(token_program: Pubkey) {
  95. let mut context = ProgramTest::new("pinocchio_token_program", TOKEN_PROGRAM_ID, None)
  96. .start_with_context()
  97. .await;
  98. let excess_lamports = 4_000_000_000_000;
  99. // Given a mint account.
  100. let mint_authority = Pubkey::new_unique();
  101. let freeze_authority = Pubkey::new_unique();
  102. let mint = mint::initialize(
  103. &mut context,
  104. mint_authority,
  105. Some(freeze_authority),
  106. &token_program,
  107. )
  108. .await
  109. .unwrap();
  110. // Given a mint authority, freeze authority and an account keypair.
  111. let owner = Keypair::new();
  112. let account = Keypair::new();
  113. let account_pubkey = account.pubkey();
  114. let account_size = size_of::<Account>();
  115. let rent = context.banks_client.get_rent().await.unwrap();
  116. let mut initialize_ix = spl_token::instruction::initialize_account(
  117. &spl_token::ID,
  118. &account.pubkey(),
  119. &mint,
  120. &owner.pubkey(),
  121. )
  122. .unwrap();
  123. // Switches the program id to the token program.
  124. initialize_ix.program_id = token_program;
  125. // When a new mint account is created and initialized.
  126. let instructions = vec![
  127. system_instruction::create_account(
  128. &context.payer.pubkey(),
  129. &account.pubkey(),
  130. rent.minimum_balance(account_size) + excess_lamports,
  131. account_size as u64,
  132. &token_program,
  133. ),
  134. initialize_ix,
  135. ];
  136. let tx = Transaction::new_signed_with_payer(
  137. &instructions,
  138. Some(&context.payer.pubkey()),
  139. &[&context.payer, &account],
  140. context.last_blockhash,
  141. );
  142. context.banks_client.process_transaction(tx).await.unwrap();
  143. let account = context
  144. .banks_client
  145. .get_account(account.pubkey())
  146. .await
  147. .unwrap();
  148. assert!(account.is_some());
  149. let account = account.unwrap();
  150. assert_eq!(
  151. account.lamports,
  152. rent.minimum_balance(account_size) + excess_lamports
  153. );
  154. // When we withdraw the excess lamports.
  155. let destination = Pubkey::new_unique();
  156. let mut withdraw_ix = spl_token_2022::instruction::withdraw_excess_lamports(
  157. &spl_token_2022::ID,
  158. &account_pubkey,
  159. &destination,
  160. &owner.pubkey(),
  161. &[],
  162. )
  163. .unwrap();
  164. // Switches the program id to the token program.
  165. withdraw_ix.program_id = token_program;
  166. let tx = Transaction::new_signed_with_payer(
  167. &[withdraw_ix],
  168. Some(&context.payer.pubkey()),
  169. &[&context.payer, &owner],
  170. context.last_blockhash,
  171. );
  172. context.banks_client.process_transaction(tx).await.unwrap();
  173. // Then the destination account has the excess lamports.
  174. let destination = context.banks_client.get_account(destination).await.unwrap();
  175. assert!(destination.is_some());
  176. let destination = destination.unwrap();
  177. assert_eq!(destination.lamports, excess_lamports);
  178. }
  179. #[test_case::test_case(TOKEN_PROGRAM_ID ; "p-token")]
  180. #[tokio::test]
  181. async fn withdraw_excess_lamports_from_multisig(token_program: Pubkey) {
  182. let context = ProgramTest::new("pinocchio_token_program", TOKEN_PROGRAM_ID, None)
  183. .start_with_context()
  184. .await;
  185. let excess_lamports = 4_000_000_000_000;
  186. // Given an account
  187. let multisig = Keypair::new();
  188. let signer1 = Keypair::new();
  189. let signer1_pubkey = signer1.pubkey();
  190. let signer2 = Keypair::new();
  191. let signer2_pubkey = signer2.pubkey();
  192. let signer3 = Keypair::new();
  193. let signer3_pubkey = signer3.pubkey();
  194. let signers = vec![&signer1_pubkey, &signer2_pubkey, &signer3_pubkey];
  195. let rent = context.banks_client.get_rent().await.unwrap();
  196. let account_size = size_of::<Multisig>();
  197. let mut initialize_ix = spl_token::instruction::initialize_multisig(
  198. &spl_token::ID,
  199. &multisig.pubkey(),
  200. &signers,
  201. 3,
  202. )
  203. .unwrap();
  204. // Switches the program id to the token program.
  205. initialize_ix.program_id = token_program;
  206. // And we initialize the multisig account.
  207. let instructions = vec![
  208. system_instruction::create_account(
  209. &context.payer.pubkey(),
  210. &multisig.pubkey(),
  211. rent.minimum_balance(account_size) + excess_lamports,
  212. account_size as u64,
  213. &token_program,
  214. ),
  215. initialize_ix,
  216. ];
  217. let tx = Transaction::new_signed_with_payer(
  218. &instructions,
  219. Some(&context.payer.pubkey()),
  220. &[&context.payer, &multisig],
  221. context.last_blockhash,
  222. );
  223. context.banks_client.process_transaction(tx).await.unwrap();
  224. let account = context
  225. .banks_client
  226. .get_account(multisig.pubkey())
  227. .await
  228. .unwrap();
  229. assert!(account.is_some());
  230. let account = account.unwrap();
  231. assert_eq!(
  232. account.lamports,
  233. rent.minimum_balance(account_size) + excess_lamports
  234. );
  235. // When we withdraw the excess lamports.
  236. let destination = Pubkey::new_unique();
  237. let mut withdraw_ix = spl_token_2022::instruction::withdraw_excess_lamports(
  238. &spl_token_2022::ID,
  239. &multisig.pubkey(),
  240. &destination,
  241. &multisig.pubkey(),
  242. &signers,
  243. )
  244. .unwrap();
  245. // Switches the program id to the token program.
  246. withdraw_ix.program_id = token_program;
  247. let tx = Transaction::new_signed_with_payer(
  248. &[withdraw_ix],
  249. Some(&context.payer.pubkey()),
  250. &[&context.payer, &signer1, &signer2, &signer3],
  251. context.last_blockhash,
  252. );
  253. context.banks_client.process_transaction(tx).await.unwrap();
  254. // Then the destination account has the excess lamports.
  255. let destination = context.banks_client.get_account(destination).await.unwrap();
  256. assert!(destination.is_some());
  257. let destination = destination.unwrap();
  258. assert_eq!(destination.lamports, excess_lamports);
  259. }
  260. #[test_case::test_case(TOKEN_PROGRAM_ID ; "p-token")]
  261. #[tokio::test]
  262. async fn fail_withdraw_excess_lamports_from_mint_wrong_authority(token_program: Pubkey) {
  263. let context = ProgramTest::new("pinocchio_token_program", TOKEN_PROGRAM_ID, None)
  264. .start_with_context()
  265. .await;
  266. let excess_lamports = 4_000_000_000_000;
  267. // Given a mint authority, freeze authority and an account keypair.
  268. let mint_authority = Keypair::new();
  269. let freeze_authority = Pubkey::new_unique();
  270. let account = Keypair::new();
  271. let account_pubkey = account.pubkey();
  272. let account_size = size_of::<Mint>();
  273. let rent = context.banks_client.get_rent().await.unwrap();
  274. let mut initialize_ix = spl_token::instruction::initialize_mint(
  275. &spl_token::ID,
  276. &account.pubkey(),
  277. &mint_authority.pubkey(),
  278. Some(&freeze_authority),
  279. 0,
  280. )
  281. .unwrap();
  282. // Switches the program id to the token program.
  283. initialize_ix.program_id = token_program;
  284. // And we initialize a mint account with excess lamports.
  285. let instructions = vec![
  286. system_instruction::create_account(
  287. &context.payer.pubkey(),
  288. &account.pubkey(),
  289. rent.minimum_balance(account_size) + excess_lamports,
  290. account_size as u64,
  291. &token_program,
  292. ),
  293. initialize_ix,
  294. ];
  295. let tx = Transaction::new_signed_with_payer(
  296. &instructions,
  297. Some(&context.payer.pubkey()),
  298. &[&context.payer, &account],
  299. context.last_blockhash,
  300. );
  301. context.banks_client.process_transaction(tx).await.unwrap();
  302. let account = context
  303. .banks_client
  304. .get_account(account.pubkey())
  305. .await
  306. .unwrap();
  307. assert!(account.is_some());
  308. let account = account.unwrap();
  309. assert_eq!(
  310. account.lamports,
  311. rent.minimum_balance(account_size) + excess_lamports
  312. );
  313. // When we try to withdraw the excess lamports with the wrong authority.
  314. let destination = Pubkey::new_unique();
  315. let wrong_authority = Keypair::new();
  316. let mut withdraw_ix = spl_token_2022::instruction::withdraw_excess_lamports(
  317. &spl_token_2022::ID,
  318. &account_pubkey,
  319. &destination,
  320. &wrong_authority.pubkey(),
  321. &[],
  322. )
  323. .unwrap();
  324. // Switches the program id to the token program.
  325. withdraw_ix.program_id = token_program;
  326. let tx = Transaction::new_signed_with_payer(
  327. &[withdraw_ix],
  328. Some(&context.payer.pubkey()),
  329. &[&context.payer, &wrong_authority],
  330. context.last_blockhash,
  331. );
  332. let error = context
  333. .banks_client
  334. .process_transaction(tx)
  335. .await
  336. .unwrap_err();
  337. // The we expect an error.
  338. assert_matches!(
  339. error,
  340. BanksClientError::TransactionError(TransactionError::InstructionError(
  341. _,
  342. InstructionError::Custom(4) // TokenError::OwnerMismatch
  343. ))
  344. );
  345. }
  346. #[test_case::test_case(TOKEN_PROGRAM_ID ; "p-token")]
  347. #[tokio::test]
  348. async fn fail_withdraw_excess_lamports_from_account_wrong_authority(token_program: Pubkey) {
  349. let mut context = ProgramTest::new("pinocchio_token_program", TOKEN_PROGRAM_ID, None)
  350. .start_with_context()
  351. .await;
  352. let excess_lamports = 4_000_000_000_000;
  353. // Given a mint account.
  354. let mint_authority = Pubkey::new_unique();
  355. let freeze_authority = Pubkey::new_unique();
  356. let mint = mint::initialize(
  357. &mut context,
  358. mint_authority,
  359. Some(freeze_authority),
  360. &token_program,
  361. )
  362. .await
  363. .unwrap();
  364. // Given a mint authority, freeze authority and an account keypair.
  365. let owner = Keypair::new();
  366. let account = Keypair::new();
  367. let account_pubkey = account.pubkey();
  368. let account_size = size_of::<Account>();
  369. let rent = context.banks_client.get_rent().await.unwrap();
  370. let mut initialize_ix = spl_token::instruction::initialize_account(
  371. &spl_token::ID,
  372. &account.pubkey(),
  373. &mint,
  374. &owner.pubkey(),
  375. )
  376. .unwrap();
  377. // Switches the program id to the token program.
  378. initialize_ix.program_id = token_program;
  379. // When a new mint account is created and initialized.
  380. let instructions = vec![
  381. system_instruction::create_account(
  382. &context.payer.pubkey(),
  383. &account.pubkey(),
  384. rent.minimum_balance(account_size) + excess_lamports,
  385. account_size as u64,
  386. &token_program,
  387. ),
  388. initialize_ix,
  389. ];
  390. let tx = Transaction::new_signed_with_payer(
  391. &instructions,
  392. Some(&context.payer.pubkey()),
  393. &[&context.payer, &account],
  394. context.last_blockhash,
  395. );
  396. context.banks_client.process_transaction(tx).await.unwrap();
  397. let account = context
  398. .banks_client
  399. .get_account(account.pubkey())
  400. .await
  401. .unwrap();
  402. assert!(account.is_some());
  403. let account = account.unwrap();
  404. assert_eq!(
  405. account.lamports,
  406. rent.minimum_balance(account_size) + excess_lamports
  407. );
  408. // When we try to withdraw the excess lamports with the wrong owner.
  409. let destination = Pubkey::new_unique();
  410. let wrong_owner = Keypair::new();
  411. let mut withdraw_ix = spl_token_2022::instruction::withdraw_excess_lamports(
  412. &spl_token_2022::ID,
  413. &account_pubkey,
  414. &destination,
  415. &wrong_owner.pubkey(),
  416. &[],
  417. )
  418. .unwrap();
  419. // Switches the program id to the token program.
  420. withdraw_ix.program_id = token_program;
  421. let tx = Transaction::new_signed_with_payer(
  422. &[withdraw_ix],
  423. Some(&context.payer.pubkey()),
  424. &[&context.payer, &wrong_owner],
  425. context.last_blockhash,
  426. );
  427. let error = context
  428. .banks_client
  429. .process_transaction(tx)
  430. .await
  431. .unwrap_err();
  432. // The we expect an error.
  433. assert_matches!(
  434. error,
  435. BanksClientError::TransactionError(TransactionError::InstructionError(
  436. _,
  437. InstructionError::Custom(4) // TokenError::OwnerMismatch
  438. ))
  439. );
  440. }
  441. #[test_case::test_case(TOKEN_PROGRAM_ID ; "p-token")]
  442. #[tokio::test]
  443. async fn fail_withdraw_excess_lamports_from_multisig_wrong_authority(token_program: Pubkey) {
  444. let context = ProgramTest::new("pinocchio_token_program", TOKEN_PROGRAM_ID, None)
  445. .start_with_context()
  446. .await;
  447. let excess_lamports = 4_000_000_000_000;
  448. // Given an account
  449. let multisig = Keypair::new();
  450. let signer1 = Keypair::new();
  451. let signer1_pubkey = signer1.pubkey();
  452. let signer2 = Keypair::new();
  453. let signer2_pubkey = signer2.pubkey();
  454. let signer3 = Keypair::new();
  455. let signer3_pubkey = signer3.pubkey();
  456. let signers = vec![&signer1_pubkey, &signer2_pubkey, &signer3_pubkey];
  457. let rent = context.banks_client.get_rent().await.unwrap();
  458. let account_size = size_of::<Multisig>();
  459. let mut initialize_ix = spl_token::instruction::initialize_multisig(
  460. &spl_token::ID,
  461. &multisig.pubkey(),
  462. &signers,
  463. 3,
  464. )
  465. .unwrap();
  466. // Switches the program id to the token program.
  467. initialize_ix.program_id = token_program;
  468. // And we initialize the multisig account.
  469. let instructions = vec![
  470. system_instruction::create_account(
  471. &context.payer.pubkey(),
  472. &multisig.pubkey(),
  473. rent.minimum_balance(account_size) + excess_lamports,
  474. account_size as u64,
  475. &token_program,
  476. ),
  477. initialize_ix,
  478. ];
  479. let tx = Transaction::new_signed_with_payer(
  480. &instructions,
  481. Some(&context.payer.pubkey()),
  482. &[&context.payer, &multisig],
  483. context.last_blockhash,
  484. );
  485. context.banks_client.process_transaction(tx).await.unwrap();
  486. let account = context
  487. .banks_client
  488. .get_account(multisig.pubkey())
  489. .await
  490. .unwrap();
  491. assert!(account.is_some());
  492. let account = account.unwrap();
  493. assert_eq!(
  494. account.lamports,
  495. rent.minimum_balance(account_size) + excess_lamports
  496. );
  497. // When we try to withdraw the excess lamports with the wrong authority.
  498. let destination = Pubkey::new_unique();
  499. let wrong_authority = Keypair::new();
  500. let mut withdraw_ix = spl_token_2022::instruction::withdraw_excess_lamports(
  501. &spl_token_2022::ID,
  502. &multisig.pubkey(),
  503. &destination,
  504. &wrong_authority.pubkey(),
  505. &signers,
  506. )
  507. .unwrap();
  508. // Switches the program id to the token program.
  509. withdraw_ix.program_id = token_program;
  510. let tx = Transaction::new_signed_with_payer(
  511. &[withdraw_ix],
  512. Some(&context.payer.pubkey()),
  513. &[&context.payer, &signer1, &signer2, &signer3],
  514. context.last_blockhash,
  515. );
  516. let error = context
  517. .banks_client
  518. .process_transaction(tx)
  519. .await
  520. .unwrap_err();
  521. // The we expect an error.
  522. assert_matches!(
  523. error,
  524. BanksClientError::TransactionError(TransactionError::InstructionError(
  525. _,
  526. InstructionError::Custom(4) // TokenError::OwnerMismatch
  527. ))
  528. );
  529. }
  530. #[test_case::test_case(TOKEN_PROGRAM_ID ; "p-token")]
  531. #[tokio::test]
  532. async fn fail_withdraw_excess_lamports_from_multisig_missing_signer(token_program: Pubkey) {
  533. let context = ProgramTest::new("pinocchio_token_program", TOKEN_PROGRAM_ID, None)
  534. .start_with_context()
  535. .await;
  536. let excess_lamports = 4_000_000_000_000;
  537. // Given an account
  538. let multisig = Keypair::new();
  539. let signer1 = Keypair::new();
  540. let signer1_pubkey = signer1.pubkey();
  541. let signer2 = Keypair::new();
  542. let signer2_pubkey = signer2.pubkey();
  543. let signer3 = Keypair::new();
  544. let signer3_pubkey = signer3.pubkey();
  545. let signers = vec![&signer1_pubkey, &signer2_pubkey, &signer3_pubkey];
  546. let rent = context.banks_client.get_rent().await.unwrap();
  547. let account_size = size_of::<Multisig>();
  548. let mut initialize_ix = spl_token::instruction::initialize_multisig(
  549. &spl_token::ID,
  550. &multisig.pubkey(),
  551. &signers,
  552. 3,
  553. )
  554. .unwrap();
  555. // Switches the program id to the token program.
  556. initialize_ix.program_id = token_program;
  557. // And we initialize the multisig account.
  558. let instructions = vec![
  559. system_instruction::create_account(
  560. &context.payer.pubkey(),
  561. &multisig.pubkey(),
  562. rent.minimum_balance(account_size) + excess_lamports,
  563. account_size as u64,
  564. &token_program,
  565. ),
  566. initialize_ix,
  567. ];
  568. let tx = Transaction::new_signed_with_payer(
  569. &instructions,
  570. Some(&context.payer.pubkey()),
  571. &[&context.payer, &multisig],
  572. context.last_blockhash,
  573. );
  574. context.banks_client.process_transaction(tx).await.unwrap();
  575. let account = context
  576. .banks_client
  577. .get_account(multisig.pubkey())
  578. .await
  579. .unwrap();
  580. assert!(account.is_some());
  581. let account = account.unwrap();
  582. assert_eq!(
  583. account.lamports,
  584. rent.minimum_balance(account_size) + excess_lamports
  585. );
  586. // When we try to withdraw the excess lamports with the wrong authority.
  587. let destination = Pubkey::new_unique();
  588. let mut withdraw_ix = spl_token_2022::instruction::withdraw_excess_lamports(
  589. &spl_token_2022::ID,
  590. &multisig.pubkey(),
  591. &destination,
  592. &multisig.pubkey(),
  593. &[&signer1_pubkey, &signer2_pubkey],
  594. )
  595. .unwrap();
  596. // Switches the program id to the token program.
  597. withdraw_ix.program_id = token_program;
  598. let tx = Transaction::new_signed_with_payer(
  599. &[withdraw_ix],
  600. Some(&context.payer.pubkey()),
  601. &[&context.payer, &signer1, &signer2],
  602. context.last_blockhash,
  603. );
  604. let error = context
  605. .banks_client
  606. .process_transaction(tx)
  607. .await
  608. .unwrap_err();
  609. // The we expect an error.
  610. assert_matches!(
  611. error,
  612. BanksClientError::TransactionError(TransactionError::InstructionError(
  613. _,
  614. InstructionError::MissingRequiredSignature
  615. ))
  616. );
  617. }