hapi_core/
context.rs

1use anchor_lang::prelude::*;
2use anchor_spl::token::{Mint, Token, TokenAccount};
3
4use crate::{
5    error::ErrorCode,
6    id,
7    state::{
8        address::{Address, Category},
9        asset::Asset,
10        case::{Case, CaseStatus},
11        community::Community,
12        network::{Network, NetworkSchema},
13        reporter::{Reporter, ReporterReward, ReporterRole, ReporterStatus},
14    },
15};
16
17#[derive(Accounts)]
18#[instruction(
19    stake_unlock_epochs: u64,
20    confirmation_threshold: u8,
21    validator_stake: u64,
22    tracer_stake: u64,
23    full_stake: u64,
24    authority_stake: u64,
25    stash_bump: u8,
26)]
27pub struct InitializeCommunity<'info> {
28    #[account(mut)]
29    pub authority: Signer<'info>,
30
31    #[account(
32        constraint = token_account.mint == stake_mint.key() @ ErrorCode::InvalidToken,
33        constraint = token_account.owner == token_signer.key() @ ProgramError::IllegalOwner,
34        owner = Token::id(),
35    )]
36    pub token_account: Account<'info, TokenAccount>,
37
38    #[account(
39        constraint = treasury_token_account.mint == stake_mint.key() @ ErrorCode::InvalidToken,
40        constraint = treasury_token_account.owner == token_signer.key() @ ProgramError::IllegalOwner,
41        owner = Token::id(),
42    )]
43    pub treasury_token_account: Account<'info, TokenAccount>,
44
45    #[account(
46        init,
47        payer = authority,
48        owner = id(),
49        space = 8 + std::mem::size_of::<Community>()
50    )]
51    pub community: Account<'info, Community>,
52
53    #[account(owner = Token::id())]
54    pub stake_mint: Account<'info, Mint>,
55
56    /// CHECK: this account is not dangerous
57    pub token_signer: AccountInfo<'info>,
58
59    pub system_program: Program<'info, System>,
60}
61
62#[derive(Accounts)]
63#[instruction(
64    stake_unlock_epochs: u64,
65    confirmation_threshold: u8,
66    validator_stake: u64,
67    tracer_stake: u64,
68    full_stake: u64,
69    authority_stake: u64,
70)]
71pub struct UpdateCommunity<'info> {
72    pub authority: Signer<'info>,
73
74    #[account(
75        mut,
76        owner = id(),
77        has_one = authority @ ErrorCode::AuthorityMismatch,
78    )]
79    pub community: Account<'info, Community>,
80}
81
82#[derive(Accounts)]
83pub struct SetCommunityAuthority<'info> {
84    pub authority: Signer<'info>,
85
86    #[account(
87        mut,
88        owner = id(),
89        has_one = authority @ ErrorCode::AuthorityMismatch,
90    )]
91    pub community: Account<'info, Community>,
92
93    /// CHECK: this account is not dangerous
94    #[account(
95        constraint = new_authority.key() != authority.key() @ ErrorCode::AuthorityMismatch,
96    )]
97    pub new_authority: AccountInfo<'info>,
98}
99
100#[derive(Accounts)]
101#[instruction(
102    name: [u8; 32],
103    schema: NetworkSchema,
104    address_tracer_reward: u64,
105    address_confirmation_reward: u64,
106    asset_tracer_reward: u64,
107    asset_confirmation_reward: u64,
108    bump: u8,
109    reward_signer_bump: u8,
110)]
111pub struct CreateNetwork<'info> {
112    #[account(mut)]
113    pub authority: Signer<'info>,
114
115    #[account(
116        owner = id(),
117        has_one = authority @ ErrorCode::AuthorityMismatch,
118    )]
119    pub community: Account<'info, Community>,
120
121    #[account(
122        mut,
123        owner = Token::id(),
124    )]
125    pub reward_mint: Account<'info, Mint>,
126
127    /// CHECK: this account is not dangerous
128    #[account(
129        seeds = [b"network_reward".as_ref(), network.key().as_ref()],
130        bump = reward_signer_bump,
131    )]
132    pub reward_signer: AccountInfo<'info>,
133
134    #[account(
135        init,
136        payer = authority,
137        owner = id(),
138        seeds = [b"network".as_ref(), community.key().as_ref(), &name],
139        bump,
140        space = 8 + std::mem::size_of::<Network>()
141    )]
142    pub network: Account<'info, Network>,
143
144    #[account(address = Token::id())]
145    pub token_program: Program<'info, Token>,
146
147    pub system_program: Program<'info, System>,
148}
149
150#[derive(Accounts)]
151#[instruction(
152    address_tracer_reward: u64,
153    address_confirmation_reward: u64,
154    asset_tracer_reward: u64,
155    asset_confirmation_reward: u64,
156)]
157pub struct UpdateNetwork<'info> {
158    pub authority: Signer<'info>,
159
160    #[account(
161        owner = id(),
162        has_one = authority @ ErrorCode::AuthorityMismatch,
163    )]
164    pub community: Account<'info, Community>,
165
166    #[account(
167        mut,
168        has_one = community @ ErrorCode::CommunityMismatch,
169        seeds = [b"network".as_ref(), community.key().as_ref(), network.name.as_ref()],
170        bump = network.bump,
171    )]
172    pub network: Account<'info, Network>,
173}
174
175#[derive(Accounts)]
176#[instruction(role: ReporterRole, name: [u8; 32], bump: u8)]
177pub struct CreateReporter<'info> {
178    #[account(mut)]
179    pub authority: Signer<'info>,
180
181    #[account(
182        owner = id(),
183        has_one = authority @ ErrorCode::AuthorityMismatch,
184    )]
185    pub community: Account<'info, Community>,
186
187    #[account(
188        init,
189        payer = authority,
190        owner = id(),
191        seeds = [b"reporter".as_ref(), community.key().as_ref(), pubkey.key().as_ref()],
192        bump,
193        space = 8 + std::mem::size_of::<Reporter>()
194    )]
195    pub reporter: Account<'info, Reporter>,
196
197    /// CHECK: this account is not dangerous
198    pub pubkey: AccountInfo<'info>,
199
200    pub system_program: Program<'info, System>,
201}
202
203#[derive(Accounts)]
204#[instruction(bump: u8)]
205pub struct InitializeReporterReward<'info> {
206    #[account(mut)]
207    pub sender: Signer<'info>,
208
209    #[account(owner = id())]
210    pub community: Account<'info, Community>,
211
212    #[account(
213        owner = id(),
214        has_one = community @ ErrorCode::CommunityMismatch,
215        seeds = [b"network".as_ref(), community.key().as_ref(), network.name.as_ref()],
216        bump = network.bump,
217    )]
218    pub network: Account<'info, Network>,
219
220    #[account(
221        owner = id(),
222        has_one = community @ ErrorCode::CommunityMismatch,
223        constraint = reporter.pubkey == sender.key() @ ErrorCode::InvalidReporter,
224        constraint = !reporter.is_frozen @ ErrorCode::FrozenReporter,
225        seeds = [b"reporter".as_ref(), community.key().as_ref(), reporter.pubkey.as_ref()],
226        bump = reporter.bump,
227    )]
228    pub reporter: Account<'info, Reporter>,
229
230    #[account(
231        init,
232        payer = sender,
233        owner = id(),
234        seeds = [b"reporter_reward".as_ref(), network.key().as_ref(), reporter.key().as_ref()],
235        bump,
236        space = 8 + std::mem::size_of::<ReporterReward>(),
237    )]
238    pub reporter_reward: AccountLoader<'info, ReporterReward>,
239
240    pub system_program: Program<'info, System>,
241}
242
243#[derive(Accounts)]
244#[instruction(role: ReporterRole, name: [u8; 32])]
245pub struct UpdateReporter<'info> {
246    pub authority: Signer<'info>,
247
248    #[account(
249        owner = id(),
250        has_one = authority @ ErrorCode::AuthorityMismatch,
251    )]
252    pub community: Account<'info, Community>,
253
254    #[account(
255        mut,
256        owner = id(),
257        has_one = community @ ErrorCode::CommunityMismatch,
258        seeds = [b"reporter".as_ref(), community.key().as_ref(), reporter.pubkey.as_ref()],
259        bump = reporter.bump,
260    )]
261    pub reporter: Account<'info, Reporter>,
262}
263
264#[derive(Accounts)]
265pub struct FreezeReporter<'info> {
266    pub authority: Signer<'info>,
267
268    #[account(
269        owner = id(),
270        has_one = authority @ ErrorCode::AuthorityMismatch,
271    )]
272    pub community: Account<'info, Community>,
273
274    #[account(
275        mut,
276        owner = id(),
277        has_one = community @ ErrorCode::CommunityMismatch,
278        seeds = [b"reporter".as_ref(), community.key().as_ref(), reporter.pubkey.as_ref()],
279        bump = reporter.bump,
280    )]
281    pub reporter: Account<'info, Reporter>,
282}
283
284#[derive(Accounts)]
285pub struct UnfreezeReporter<'info> {
286    pub authority: Signer<'info>,
287
288    #[account(
289        owner = id(),
290        has_one = authority @ ErrorCode::AuthorityMismatch,
291    )]
292    pub community: Account<'info, Community>,
293
294    #[account(
295        mut,
296        owner = id(),
297        has_one = community @ ErrorCode::CommunityMismatch,
298        seeds = [b"reporter".as_ref(), community.key().as_ref(), reporter.pubkey.as_ref()],
299        bump = reporter.bump,
300    )]
301    pub reporter: Account<'info, Reporter>,
302}
303
304#[derive(Accounts)]
305#[instruction(case_id: u64, name: [u8; 32], bump: u8)]
306pub struct CreateCase<'info> {
307    #[account(mut)]
308    pub sender: Signer<'info>,
309
310    #[account(
311        mut,
312        owner = id()
313    )]
314    pub community: Account<'info, Community>,
315
316    #[account(
317        owner = id(),
318        has_one = community @ ErrorCode::CommunityMismatch,
319        constraint = reporter.role == ReporterRole::Publisher || reporter.role == ReporterRole::Authority @ ErrorCode::Unauthorized,
320        constraint = reporter.pubkey == sender.key() @ ErrorCode::InvalidReporter,
321        constraint = reporter.status == ReporterStatus::Active @ ErrorCode::InvalidReporterStatus,
322        constraint = !reporter.is_frozen @ ErrorCode::FrozenReporter,
323        seeds = [b"reporter".as_ref(), community.key().as_ref(), reporter.pubkey.as_ref()],
324        bump = reporter.bump,
325    )]
326    pub reporter: Account<'info, Reporter>,
327
328    #[account(
329        init,
330        payer = sender,
331        owner = id(),
332        seeds = [b"case".as_ref(), community.key().as_ref(), &case_id.to_le_bytes()],
333        bump,
334        space = 8 + std::mem::size_of::<Case>()
335    )]
336    pub case: Account<'info, Case>,
337
338    pub system_program: Program<'info, System>,
339}
340
341#[derive(Accounts)]
342#[instruction(name: [u8; 32], status: CaseStatus)]
343pub struct UpdateCase<'info> {
344    #[account(mut)]
345    pub sender: Signer<'info>,
346
347    #[account(
348        mut,
349        owner = id()
350    )]
351    pub community: Account<'info, Community>,
352
353    #[account(
354        owner = id(),
355        has_one = community @ ErrorCode::CommunityMismatch,
356        constraint = (reporter.role == ReporterRole::Publisher
357            && case.reporter == reporter.key())
358            || reporter.role == ReporterRole::Authority @ ErrorCode::Unauthorized,
359        constraint = reporter.pubkey == sender.key() @ ErrorCode::InvalidReporter,
360        constraint = reporter.status == ReporterStatus::Active @ ErrorCode::InvalidReporterStatus,
361        constraint = !reporter.is_frozen @ ErrorCode::FrozenReporter,
362        seeds = [b"reporter".as_ref(), community.key().as_ref(), reporter.pubkey.as_ref()],
363        bump = reporter.bump,
364    )]
365    pub reporter: Account<'info, Reporter>,
366
367    #[account(
368        mut,
369        has_one = community,
370        owner = id(),
371        seeds = [b"case".as_ref(), community.key().as_ref(), &case.id.to_le_bytes()],
372        bump = case.bump,
373    )]
374    pub case: Account<'info, Case>,
375}
376
377#[derive(Accounts)]
378#[instruction(addr: [u8; 64], category: Category, risk: u8, bump: u8)]
379pub struct CreateAddress<'info> {
380    #[account(mut)]
381    pub sender: Signer<'info>,
382
383    pub community: Box<Account<'info, Community>>,
384
385    #[account(
386        has_one = community @ ErrorCode::CommunityMismatch,
387        seeds = [b"network".as_ref(), community.key().as_ref(), network.name.as_ref()],
388        bump = network.bump,
389    )]
390    pub network: Box<Account<'info, Network>>,
391
392    #[account(
393        owner = id(),
394        has_one = community @ ErrorCode::CommunityMismatch,
395        constraint = reporter.role == ReporterRole::Tracer
396            || reporter.role == ReporterRole::Publisher
397            || reporter.role == ReporterRole::Authority @ ErrorCode::Unauthorized,
398        constraint = reporter.pubkey == sender.key() @ ErrorCode::InvalidReporter,
399        constraint = reporter.status == ReporterStatus::Active @ ErrorCode::InvalidReporterStatus,
400        constraint = !reporter.is_frozen @ ErrorCode::FrozenReporter,
401        seeds = [b"reporter".as_ref(), community.key().as_ref(), reporter.pubkey.as_ref()],
402        bump = reporter.bump,
403    )]
404    pub reporter: Account<'info, Reporter>,
405
406    #[account(
407        owner = id(),
408        has_one = community @ ErrorCode::CommunityMismatch,
409        constraint = case.status == CaseStatus::Open @ ErrorCode::CaseClosed,
410        seeds = [b"case".as_ref(), community.key().as_ref(), &case.id.to_le_bytes()],
411        bump = case.bump,
412    )]
413    pub case: Account<'info, Case>,
414
415    #[account(
416        init,
417        owner = id(),
418        payer = sender,
419        seeds = [
420            b"address".as_ref(),
421            network.key().as_ref(),
422            addr[0..32].as_ref(),
423            addr[32..64].as_ref(),
424        ],
425        bump,
426        space = 8 + std::mem::size_of::<Address>()
427    )]
428    pub address: Account<'info, Address>,
429
430    #[account(
431        mut,
432        constraint = reporter_payment_token_account.mint == community.stake_mint.key() @ ErrorCode::InvalidToken,
433        constraint = reporter_payment_token_account.owner == sender.key() @ ProgramError::IllegalOwner,
434    )]
435    pub reporter_payment_token_account: Account<'info, TokenAccount>,
436
437    #[account(
438        mut,
439        constraint = treasury_token_account.mint == community.stake_mint.key() @ ErrorCode::InvalidToken,
440        constraint = treasury_token_account.owner == community.token_signer.key() @ ProgramError::IllegalOwner,
441        owner = Token::id(),
442    )]
443    pub treasury_token_account: Account<'info, TokenAccount>,
444
445    #[account(address = Token::id())]
446    pub token_program: Program<'info, Token>,
447
448    pub system_program: Program<'info, System>,
449}
450
451#[derive(Accounts)]
452#[instruction(category: Category, risk: u8)]
453pub struct UpdateAddress<'info> {
454    #[account(mut)]
455    pub sender: Signer<'info>,
456
457    pub community: Box<Account<'info, Community>>,
458
459    #[account(
460        has_one = community @ ErrorCode::CommunityMismatch,
461        seeds = [b"network".as_ref(), community.key().as_ref(), network.name.as_ref()],
462        bump = network.bump,
463    )]
464    pub network: Box<Account<'info, Network>>,
465
466    #[account(
467        owner = id(),
468        has_one = community @ ErrorCode::CommunityMismatch,
469        constraint = reporter.role == ReporterRole::Authority
470            || (reporter.role == ReporterRole::Publisher
471            && case.reporter == reporter.key()) @ ErrorCode::Unauthorized,
472        constraint = reporter.pubkey == sender.key() @ ErrorCode::InvalidReporter,
473        constraint = reporter.status == ReporterStatus::Active @ ErrorCode::InvalidReporterStatus,
474        constraint = !reporter.is_frozen @ ErrorCode::FrozenReporter,
475        seeds = [b"reporter".as_ref(), community.key().as_ref(), reporter.pubkey.as_ref()],
476        bump = reporter.bump,
477    )]
478    pub reporter: Account<'info, Reporter>,
479
480    #[account(
481        owner = id(),
482        has_one = community @ ErrorCode::CommunityMismatch,
483        constraint = case.status == CaseStatus::Open @ ErrorCode::CaseClosed,
484        seeds = [b"case".as_ref(), community.key().as_ref(), &case.id.to_le_bytes()],
485        bump = case.bump,
486    )]
487    pub case: Account<'info, Case>,
488
489    #[account(
490        mut,
491        owner = id(),
492        constraint = case.id == address.case_id @ ErrorCode::CaseMismatch,
493        has_one = network @ ErrorCode::NetworkMismatch,
494        seeds = [
495            b"address".as_ref(),
496            network.key().as_ref(),
497            address.address[0..32].as_ref(),
498            address.address[32..64].as_ref(),
499        ],
500        bump = address.bump,
501    )]
502    pub address: Account<'info, Address>,
503
504    #[account(
505        mut,
506        constraint = reporter_payment_token_account.mint == community.stake_mint.key() @ ErrorCode::InvalidToken,
507        constraint = reporter_payment_token_account.owner == sender.key() @ ProgramError::IllegalOwner,
508    )]
509    pub reporter_payment_token_account: Account<'info, TokenAccount>,
510
511    #[account(
512        mut,
513        constraint = treasury_token_account.mint == community.stake_mint.key() @ ErrorCode::InvalidToken,
514        constraint = treasury_token_account.owner == community.token_signer.key() @ ProgramError::IllegalOwner,
515        owner = Token::id(),
516    )]
517    pub treasury_token_account: Account<'info, TokenAccount>,
518
519    #[account(address = Token::id())]
520    pub token_program: Program<'info, Token>,
521}
522
523#[derive(Accounts)]
524pub struct ChangeAddressCase<'info> {
525    #[account(mut)]
526    pub sender: Signer<'info>,
527
528    #[account(owner = id())]
529    pub community: Account<'info, Community>,
530
531    #[account(
532        owner = id(),
533        has_one = community @ ErrorCode::CommunityMismatch,
534        seeds = [b"network".as_ref(), community.key().as_ref(), network.name.as_ref()],
535        bump = network.bump,
536    )]
537    pub network: Account<'info, Network>,
538
539    #[account(
540        owner = id(),
541        has_one = community @ ErrorCode::CommunityMismatch,
542        constraint = reporter.role == ReporterRole::Authority
543            || (reporter.role == ReporterRole::Publisher
544            && new_case.reporter == reporter.key()) @ ErrorCode::Unauthorized,
545        constraint = reporter.pubkey == sender.key() @ ErrorCode::InvalidReporter,
546        constraint = reporter.status == ReporterStatus::Active @ ErrorCode::InvalidReporterStatus,
547        constraint = !reporter.is_frozen @ ErrorCode::FrozenReporter,
548        seeds = [b"reporter".as_ref(), community.key().as_ref(), reporter.pubkey.as_ref()],
549        bump = reporter.bump,
550    )]
551    pub reporter: Account<'info, Reporter>,
552
553    #[account(
554        owner = id(),
555        has_one = community @ ErrorCode::CommunityMismatch,
556        constraint = new_case.status == CaseStatus::Open @ ErrorCode::CaseClosed,
557        constraint = new_case.id != address.case_id @ ErrorCode::SameCase,
558        seeds = [b"case".as_ref(), community.key().as_ref(), &new_case.id.to_le_bytes()],
559        bump = new_case.bump,
560    )]
561    pub new_case: Account<'info, Case>,
562
563    #[account(
564        mut,
565        owner = id(),
566        has_one = network @ ErrorCode::NetworkMismatch,
567        seeds = [
568            b"address".as_ref(),
569            network.key().as_ref(),
570            address.address[0..32].as_ref(),
571            address.address[32..64].as_ref(),
572        ],
573        bump = address.bump,
574    )]
575    pub address: Account<'info, Address>,
576}
577
578#[derive(Accounts)]
579pub struct ConfirmAddress<'info> {
580    #[account(mut)]
581    pub sender: Signer<'info>,
582
583    #[account(owner = id())]
584    pub community: Account<'info, Community>,
585
586    #[account(
587        owner = id(),
588        has_one = community @ ErrorCode::CommunityMismatch,
589        seeds = [b"network".as_ref(), community.key().as_ref(), network.name.as_ref()],
590        bump = network.bump,
591    )]
592    pub network: Account<'info, Network>,
593
594    #[account(
595        owner = id(),
596        has_one = community @ ErrorCode::CommunityMismatch,
597        constraint = reporter.pubkey == sender.key() @ ErrorCode::InvalidReporter,
598        constraint = reporter.status == ReporterStatus::Active @ ErrorCode::InvalidReporterStatus,
599        constraint = !reporter.is_frozen @ ErrorCode::FrozenReporter,
600        seeds = [b"reporter".as_ref(), community.key().as_ref(), reporter.pubkey.as_ref()],
601        bump = reporter.bump,
602    )]
603    pub reporter: Account<'info, Reporter>,
604
605    #[account(
606        mut,
607        owner = id(),
608        has_one = reporter,
609        has_one = network,
610        seeds = [b"reporter_reward".as_ref(), network.key().as_ref(), reporter.key().as_ref()],
611        bump = reporter_reward.load()?.bump,
612    )]
613    pub reporter_reward: AccountLoader<'info, ReporterReward>,
614
615    #[account(
616        mut,
617        owner = id(),
618        has_one = network,
619        constraint = address_reporter_reward.load()?.reporter == address.reporter @ ErrorCode::InvalidReporter,
620        seeds = [b"reporter_reward".as_ref(), network.key().as_ref(), address.reporter.as_ref()],
621        bump = address_reporter_reward.load()?.bump,
622    )]
623    pub address_reporter_reward: AccountLoader<'info, ReporterReward>,
624
625    #[account(
626        owner = id(),
627        has_one = community @ ErrorCode::CommunityMismatch,
628        constraint = case.status == CaseStatus::Open @ ErrorCode::CaseClosed,
629        seeds = [b"case".as_ref(), community.key().as_ref(), &case.id.to_le_bytes()],
630        bump = case.bump,
631    )]
632    pub case: Account<'info, Case>,
633
634    #[account(
635        mut,
636        owner = id(),
637        constraint = case.id == address.case_id @ ErrorCode::CaseMismatch,
638        constraint = address.reporter != reporter.key() @ ErrorCode::Unauthorized,
639        has_one = network @ ErrorCode::NetworkMismatch,
640        seeds = [
641            b"address".as_ref(),
642            network.key().as_ref(),
643            address.address[0..32].as_ref(),
644            address.address[32..64].as_ref(),
645        ],
646        bump = address.bump,
647    )]
648    pub address: Account<'info, Address>,
649}
650
651#[derive(Accounts)]
652#[instruction(mint: [u8; 64], asset_id: [u8; 32], category: Category, risk: u8, bump: u8)]
653pub struct CreateAsset<'info> {
654    #[account(mut)]
655    pub sender: Signer<'info>,
656
657    pub community: Box<Account<'info, Community>>,
658
659    #[account(
660        has_one = community @ ErrorCode::CommunityMismatch,
661        seeds = [b"network".as_ref(), community.key().as_ref(), network.name.as_ref()],
662        bump = network.bump,
663    )]
664    pub network: Box<Account<'info, Network>>,
665
666    #[account(
667        owner = id(),
668        has_one = community @ ErrorCode::CommunityMismatch,
669        constraint = reporter.role == ReporterRole::Tracer
670            || reporter.role == ReporterRole::Publisher
671            || reporter.role == ReporterRole::Authority @ ErrorCode::Unauthorized,
672        constraint = reporter.pubkey == sender.key() @ ErrorCode::InvalidReporter,
673        constraint = reporter.status == ReporterStatus::Active @ ErrorCode::InvalidReporterStatus,
674        constraint = !reporter.is_frozen @ ErrorCode::FrozenReporter,
675        seeds = [b"reporter".as_ref(), community.key().as_ref(), reporter.pubkey.as_ref()],
676        bump = reporter.bump,
677    )]
678    pub reporter: Account<'info, Reporter>,
679
680    #[account(
681        owner = id(),
682        has_one = community @ ErrorCode::CommunityMismatch,
683        constraint = case.status == CaseStatus::Open @ ErrorCode::CaseClosed,
684        seeds = [b"case".as_ref(), community.key().as_ref(), &case.id.to_le_bytes()],
685        bump = case.bump,
686    )]
687    pub case: Account<'info, Case>,
688
689    #[account(
690        init,
691        payer = sender,
692        seeds = [
693            b"asset".as_ref(),
694            network.key().as_ref(),
695            mint[0..32].as_ref(),
696            mint[32..64].as_ref(),
697            asset_id.as_ref(),
698        ],
699        bump,
700        space = 8 + std::mem::size_of::<Asset>()
701    )]
702    pub asset: Box<Account<'info, Asset>>,
703
704    #[account(
705        mut,
706        constraint = reporter_payment_token_account.mint == community.stake_mint.key() @ ErrorCode::InvalidToken,
707        constraint = reporter_payment_token_account.owner == sender.key() @ ProgramError::IllegalOwner,
708    )]
709    pub reporter_payment_token_account: Account<'info, TokenAccount>,
710
711    #[account(
712        mut,
713        constraint = treasury_token_account.mint == community.stake_mint.key() @ ErrorCode::InvalidToken,
714        constraint = treasury_token_account.owner == community.token_signer.key() @ ProgramError::IllegalOwner,
715        owner = Token::id(),
716    )]
717    pub treasury_token_account: Account<'info, TokenAccount>,
718
719    #[account(address = Token::id())]
720    pub token_program: Program<'info, Token>,
721
722    pub system_program: Program<'info, System>,
723}
724
725#[derive(Accounts)]
726#[instruction(category: Category, risk: u8)]
727pub struct UpdateAsset<'info> {
728    #[account(mut)]
729    pub sender: Signer<'info>,
730
731    pub community: Box<Account<'info, Community>>,
732
733    #[account(
734        has_one = community @ ErrorCode::CommunityMismatch,
735        seeds = [b"network".as_ref(), community.key().as_ref(), network.name.as_ref()],
736        bump = network.bump,
737    )]
738    pub network: Box<Account<'info, Network>>,
739
740    #[account(
741        owner = id(),
742        has_one = community @ ErrorCode::CommunityMismatch,
743        constraint = reporter.role == ReporterRole::Authority
744            || (reporter.role == ReporterRole::Publisher
745            && case.reporter == reporter.key()) @ ErrorCode::Unauthorized,
746        constraint = reporter.pubkey == sender.key() @ ErrorCode::InvalidReporter,
747        constraint = reporter.status == ReporterStatus::Active @ ErrorCode::InvalidReporterStatus,
748        constraint = !reporter.is_frozen @ ErrorCode::FrozenReporter,
749        seeds = [b"reporter".as_ref(), community.key().as_ref(), reporter.pubkey.as_ref()],
750        bump = reporter.bump,
751    )]
752    pub reporter: Account<'info, Reporter>,
753
754    #[account(
755        owner = id(),
756        has_one = community @ ErrorCode::CommunityMismatch,
757        constraint = case.status == CaseStatus::Open @ ErrorCode::CaseClosed,
758        seeds = [b"case".as_ref(), community.key().as_ref(), &case.id.to_le_bytes()],
759        bump = case.bump,
760    )]
761    pub case: Account<'info, Case>,
762
763    #[account(
764        mut,
765        owner = id(),
766        constraint = case.id == asset.case_id @ ErrorCode::CaseMismatch,
767        has_one = network @ ErrorCode::NetworkMismatch,
768        seeds = [
769            b"asset".as_ref(),
770            network.key().as_ref(),
771            asset.mint[0..32].as_ref(),
772            asset.mint[32..64].as_ref(),
773            asset.asset_id.as_ref(),
774        ],
775        bump = asset.bump,
776    )]
777    pub asset: Account<'info, Asset>,
778
779    #[account(
780        mut,
781        constraint = reporter_payment_token_account.mint == community.stake_mint.key() @ ErrorCode::InvalidToken,
782        constraint = reporter_payment_token_account.owner == sender.key() @ ProgramError::IllegalOwner,
783    )]
784    pub reporter_payment_token_account: Account<'info, TokenAccount>,
785
786    #[account(
787        mut,
788        constraint = treasury_token_account.mint == community.stake_mint.key() @ ErrorCode::InvalidToken,
789        constraint = treasury_token_account.owner == community.token_signer.key() @ ProgramError::IllegalOwner,
790        owner = Token::id(),
791    )]
792    pub treasury_token_account: Account<'info, TokenAccount>,
793
794    #[account(address = Token::id())]
795    pub token_program: Program<'info, Token>,
796}
797
798#[derive(Accounts)]
799pub struct ConfirmAsset<'info> {
800    #[account(mut)]
801    pub sender: Signer<'info>,
802
803    #[account(owner = id())]
804    pub community: Account<'info, Community>,
805
806    #[account(
807        owner = id(),
808        has_one = community @ ErrorCode::CommunityMismatch,
809        seeds = [b"network".as_ref(), community.key().as_ref(), network.name.as_ref()],
810        bump = network.bump,
811    )]
812    pub network: Account<'info, Network>,
813
814    #[account(
815        owner = id(),
816        has_one = community @ ErrorCode::CommunityMismatch,
817        constraint = reporter.pubkey == sender.key() @ ErrorCode::InvalidReporter,
818        constraint = reporter.status == ReporterStatus::Active @ ErrorCode::InvalidReporterStatus,
819        constraint = !reporter.is_frozen @ ErrorCode::FrozenReporter,
820        seeds = [b"reporter".as_ref(), community.key().as_ref(), reporter.pubkey.as_ref()],
821        bump = reporter.bump,
822    )]
823    pub reporter: Account<'info, Reporter>,
824
825    #[account(
826        mut,
827        owner = id(),
828        has_one = reporter,
829        has_one = network,
830        seeds = [b"reporter_reward".as_ref(), network.key().as_ref(), reporter.key().as_ref()],
831        bump = reporter_reward.load()?.bump,
832    )]
833    pub reporter_reward: AccountLoader<'info, ReporterReward>,
834
835    #[account(
836        mut,
837        owner = id(),
838        has_one = network,
839        constraint = asset_reporter_reward.load()?.reporter == asset.reporter @ ErrorCode::InvalidReporter,
840        seeds = [b"reporter_reward".as_ref(), network.key().as_ref(), asset.reporter.as_ref()],
841        bump = asset_reporter_reward.load()?.bump,
842    )]
843    pub asset_reporter_reward: AccountLoader<'info, ReporterReward>,
844
845    #[account(
846        owner = id(),
847        has_one = community @ ErrorCode::CommunityMismatch,
848        constraint = case.status == CaseStatus::Open @ ErrorCode::CaseClosed,
849        seeds = [b"case".as_ref(), community.key().as_ref(), &case.id.to_le_bytes()],
850        bump = case.bump,
851    )]
852    pub case: Account<'info, Case>,
853
854    #[account(
855        mut,
856        owner = id(),
857        constraint = case.id == asset.case_id @ ErrorCode::CaseMismatch,
858        constraint = asset.reporter != reporter.key() @ ErrorCode::Unauthorized,
859        has_one = network @ ErrorCode::NetworkMismatch,
860        seeds = [
861            b"asset".as_ref(),
862            network.key().as_ref(),
863            asset.mint[0..32].as_ref(),
864            asset.mint[32..64].as_ref(),
865            asset.asset_id.as_ref(),
866        ],
867        bump = asset.bump,
868    )]
869    pub asset: Account<'info, Asset>,
870}
871
872#[derive(Accounts)]
873pub struct ActivateReporter<'info> {
874    #[account(mut)]
875    pub sender: Signer<'info>,
876
877    #[account(owner = id())]
878    pub community: Account<'info, Community>,
879
880    #[account(
881        constraint = community.stake_mint == stake_mint.key() @ ErrorCode::InvalidMint
882    )]
883    pub stake_mint: Account<'info, Mint>,
884
885    #[account(
886        mut,
887        constraint = reporter_token_account.mint == stake_mint.key() @ ErrorCode::InvalidToken,
888        constraint = reporter_token_account.owner == sender.key() @ ProgramError::IllegalOwner,
889    )]
890    pub reporter_token_account: Account<'info, TokenAccount>,
891
892    #[account(
893        mut,
894        constraint = community_token_account.mint == stake_mint.key() @ ErrorCode::InvalidToken,
895    )]
896    pub community_token_account: Account<'info, TokenAccount>,
897
898    #[account(address = Token::id())]
899    pub token_program: Program<'info, Token>,
900
901    #[account(
902        mut,
903        owner = id(),
904        has_one = community @ ErrorCode::CommunityMismatch,
905        constraint = reporter.status == ReporterStatus::Inactive @ ErrorCode::InvalidReporterStatus,
906        constraint = reporter.pubkey == sender.key() @ ErrorCode::InvalidReporter,
907        constraint = !reporter.is_frozen @ ErrorCode::FrozenReporter,
908        seeds = [b"reporter".as_ref(), community.key().as_ref(), reporter.pubkey.as_ref()],
909        bump = reporter.bump,
910    )]
911    pub reporter: Account<'info, Reporter>,
912}
913
914#[derive(Accounts)]
915pub struct DeactivateReporter<'info> {
916    #[account(mut)]
917    pub sender: Signer<'info>,
918
919    #[account(owner = id())]
920    pub community: Account<'info, Community>,
921
922    #[account(
923        mut,
924        owner = id(),
925        has_one = community @ ErrorCode::CommunityMismatch,
926        constraint = reporter.status == ReporterStatus::Active @ ErrorCode::InvalidReporterStatus,
927        constraint = reporter.pubkey == sender.key() @ ErrorCode::InvalidReporter,
928        constraint = !reporter.is_frozen @ ErrorCode::FrozenReporter,
929        seeds = [b"reporter".as_ref(), community.key().as_ref(), reporter.pubkey.as_ref()],
930        bump = reporter.bump,
931    )]
932    pub reporter: Account<'info, Reporter>,
933}
934
935#[derive(Accounts)]
936pub struct ReleaseReporter<'info> {
937    #[account(mut)]
938    pub sender: Signer<'info>,
939
940    #[account(owner = id())]
941    pub community: Account<'info, Community>,
942
943    #[account(
944        constraint = community.stake_mint == stake_mint.key() @ ErrorCode::InvalidMint
945    )]
946    pub stake_mint: Account<'info, Mint>,
947
948    #[account(
949        mut,
950        constraint = reporter_token_account.mint == stake_mint.key() @ ErrorCode::InvalidToken,
951        constraint = reporter_token_account.owner == sender.key() @ ProgramError::IllegalOwner,
952    )]
953    pub reporter_token_account: Account<'info, TokenAccount>,
954
955    /// CHECK: this account is not dangerous
956    #[account(
957        seeds = [b"community_stash".as_ref(), community.key().as_ref()],
958        bump = community.token_signer_bump,
959    )]
960    pub community_token_signer: AccountInfo<'info>,
961
962    #[account(
963        mut,
964        constraint = community_token_account.mint == stake_mint.key() @ ErrorCode::InvalidToken,
965        constraint = community_token_account.owner == community_token_signer.key() @ ProgramError::IllegalOwner,
966    )]
967    pub community_token_account: Account<'info, TokenAccount>,
968
969    #[account(address = Token::id())]
970    pub token_program: Program<'info, Token>,
971
972    #[account(
973        mut,
974        owner = id(),
975        has_one = community @ ErrorCode::CommunityMismatch,
976        constraint = reporter.status == ReporterStatus::Unstaking @ ErrorCode::InvalidReporterStatus,
977        constraint = reporter.pubkey == sender.key() @ ErrorCode::InvalidReporter,
978        constraint = !reporter.is_frozen @ ErrorCode::FrozenReporter,
979        seeds = [b"reporter".as_ref(), community.key().as_ref(), reporter.pubkey.as_ref()],
980        bump = reporter.bump,
981    )]
982    pub reporter: Account<'info, Reporter>,
983}
984
985#[derive(Accounts)]
986pub struct ClaimReporterReward<'info> {
987    #[account(mut)]
988    pub sender: Signer<'info>,
989
990    #[account(owner = id())]
991    pub community: Account<'info, Community>,
992
993    #[account(
994        owner = id(),
995        has_one = community @ ErrorCode::CommunityMismatch,
996        seeds = [b"network".as_ref(), community.key().as_ref(), network.name.as_ref()],
997        bump = network.bump,
998    )]
999    pub network: Account<'info, Network>,
1000
1001    #[account(
1002        owner = id(),
1003        has_one = community @ ErrorCode::CommunityMismatch,
1004        constraint = reporter.pubkey == sender.key() @ ErrorCode::InvalidReporter,
1005        constraint = !reporter.is_frozen @ ErrorCode::FrozenReporter,
1006        seeds = [b"reporter".as_ref(), community.key().as_ref(), reporter.pubkey.as_ref()],
1007        bump = reporter.bump,
1008    )]
1009    pub reporter: Account<'info, Reporter>,
1010
1011    #[account(
1012        mut,
1013        owner = id(),
1014        has_one = reporter,
1015        has_one = network,
1016        seeds = [b"reporter_reward".as_ref(), network.key().as_ref(), reporter.key().as_ref()],
1017        bump = reporter_reward.load()?.bump,
1018    )]
1019    pub reporter_reward: AccountLoader<'info, ReporterReward>,
1020
1021    #[account(
1022        mut,
1023        constraint = reporter_token_account.mint == reward_mint.key() @ ErrorCode::InvalidToken,
1024        constraint = reporter_token_account.owner == sender.key() @ ProgramError::IllegalOwner,
1025    )]
1026    pub reporter_token_account: Account<'info, TokenAccount>,
1027
1028    #[account(
1029        mut,
1030        owner = Token::id())
1031    ]
1032    pub reward_mint: Account<'info, Mint>,
1033
1034    /// CHECK: this account is not dangerous
1035    #[account(
1036        seeds = [b"network_reward".as_ref(), network.key().as_ref()],
1037        bump = network.reward_signer_bump,
1038    )]
1039    pub reward_signer: AccountInfo<'info>,
1040
1041    #[account(address = Token::id())]
1042    pub token_program: Program<'info, Token>,
1043}
1044
1045#[derive(Accounts)]
1046#[instruction(price: u64)]
1047pub struct UpdateReplicationPrice<'info> {
1048    #[account(mut)]
1049    pub sender: Signer<'info>,
1050
1051    pub community: Box<Account<'info, Community>>,
1052
1053    #[account(
1054        mut,
1055        has_one = community @ ErrorCode::CommunityMismatch,
1056        seeds = [b"network".as_ref(), community.key().as_ref(), network.name.as_ref()],
1057        bump = network.bump,
1058    )]
1059    pub network: Box<Account<'info, Network>>,
1060
1061    #[account(
1062        owner = id(),
1063        has_one = community @ ErrorCode::CommunityMismatch,
1064        constraint = reporter.role == ReporterRole::Appraiser @ ErrorCode::Unauthorized,
1065        constraint = reporter.pubkey == sender.key() @ ErrorCode::InvalidReporter,
1066        constraint = reporter.status == ReporterStatus::Active @ ErrorCode::InvalidReporterStatus,
1067        constraint = !reporter.is_frozen @ ErrorCode::FrozenReporter,
1068        seeds = [b"reporter".as_ref(), community.key().as_ref(), reporter.pubkey.as_ref()],
1069        bump = reporter.bump,
1070    )]
1071    pub reporter: Account<'info, Reporter>,
1072}