constraints.rs 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990
  1. use crate::*;
  2. use syn::ext::IdentExt;
  3. use syn::parse::{Error as ParseError, Parse, ParseStream, Result as ParseResult};
  4. use syn::punctuated::Punctuated;
  5. use syn::spanned::Spanned;
  6. use syn::token::Comma;
  7. use syn::{bracketed, Expr, Ident, LitStr, Token};
  8. pub fn parse(
  9. f: &syn::Field,
  10. f_ty: Option<&Ty>,
  11. has_instruction_api: bool,
  12. ) -> ParseResult<(ConstraintGroup, ConstraintGroup)> {
  13. let mut constraints = ConstraintGroupBuilder::new(f_ty);
  14. for attr in f.attrs.iter().filter(is_account) {
  15. for c in attr.parse_args_with(Punctuated::<ConstraintToken, Comma>::parse_terminated)? {
  16. constraints.add(c)?;
  17. }
  18. }
  19. let account_constraints = constraints.build()?;
  20. let mut constraints = ConstraintGroupBuilder::new(f_ty);
  21. for attr in f.attrs.iter().filter(is_instruction) {
  22. if !has_instruction_api {
  23. return Err(ParseError::new(
  24. attr.span(),
  25. "an instruction api must be declared",
  26. ));
  27. }
  28. for c in attr.parse_args_with(Punctuated::<ConstraintToken, Comma>::parse_terminated)? {
  29. constraints.add(c)?;
  30. }
  31. }
  32. let instruction_constraints = constraints.build()?;
  33. Ok((account_constraints, instruction_constraints))
  34. }
  35. pub fn is_account(attr: &&syn::Attribute) -> bool {
  36. attr.path
  37. .get_ident()
  38. .map_or(false, |ident| ident == "account")
  39. }
  40. pub fn is_instruction(attr: &&syn::Attribute) -> bool {
  41. attr.path
  42. .get_ident()
  43. .map_or(false, |ident| ident == "instruction")
  44. }
  45. // Parses a single constraint from a parse stream for `#[account(<STREAM>)]`.
  46. pub fn parse_token(stream: ParseStream) -> ParseResult<ConstraintToken> {
  47. let is_lit = stream.peek(LitStr);
  48. if is_lit {
  49. let lit: LitStr = stream.parse()?;
  50. let c = ConstraintToken::Literal(Context::new(lit.span(), ConstraintLiteral { lit }));
  51. return Ok(c);
  52. }
  53. let ident = stream.call(Ident::parse_any)?;
  54. let kw = ident.to_string();
  55. let c = match kw.as_str() {
  56. "init" => ConstraintToken::Init(Context::new(
  57. ident.span(),
  58. ConstraintInit { if_needed: false },
  59. )),
  60. "init_if_needed" => ConstraintToken::Init(Context::new(
  61. ident.span(),
  62. ConstraintInit { if_needed: true },
  63. )),
  64. "zero" => ConstraintToken::Zeroed(Context::new(ident.span(), ConstraintZeroed {})),
  65. "mut" => ConstraintToken::Mut(Context::new(
  66. ident.span(),
  67. ConstraintMut {
  68. error: parse_optional_custom_error(&stream)?,
  69. },
  70. )),
  71. "signer" => ConstraintToken::Signer(Context::new(
  72. ident.span(),
  73. ConstraintSigner {
  74. error: parse_optional_custom_error(&stream)?,
  75. },
  76. )),
  77. "executable" => {
  78. ConstraintToken::Executable(Context::new(ident.span(), ConstraintExecutable {}))
  79. }
  80. "mint" => {
  81. stream.parse::<Token![:]>()?;
  82. stream.parse::<Token![:]>()?;
  83. let kw = stream.call(Ident::parse_any)?.to_string();
  84. stream.parse::<Token![=]>()?;
  85. let span = ident
  86. .span()
  87. .join(stream.span())
  88. .unwrap_or_else(|| ident.span());
  89. match kw.as_str() {
  90. "authority" => ConstraintToken::MintAuthority(Context::new(
  91. span,
  92. ConstraintMintAuthority {
  93. mint_auth: stream.parse()?,
  94. },
  95. )),
  96. "freeze_authority" => ConstraintToken::MintFreezeAuthority(Context::new(
  97. span,
  98. ConstraintMintFreezeAuthority {
  99. mint_freeze_auth: stream.parse()?,
  100. },
  101. )),
  102. "decimals" => ConstraintToken::MintDecimals(Context::new(
  103. span,
  104. ConstraintMintDecimals {
  105. decimals: stream.parse()?,
  106. },
  107. )),
  108. _ => return Err(ParseError::new(ident.span(), "Invalid attribute")),
  109. }
  110. }
  111. "token" => {
  112. stream.parse::<Token![:]>()?;
  113. stream.parse::<Token![:]>()?;
  114. let kw = stream.call(Ident::parse_any)?.to_string();
  115. stream.parse::<Token![=]>()?;
  116. let span = ident
  117. .span()
  118. .join(stream.span())
  119. .unwrap_or_else(|| ident.span());
  120. match kw.as_str() {
  121. "mint" => ConstraintToken::TokenMint(Context::new(
  122. span,
  123. ConstraintTokenMint {
  124. mint: stream.parse()?,
  125. },
  126. )),
  127. "authority" => ConstraintToken::TokenAuthority(Context::new(
  128. span,
  129. ConstraintTokenAuthority {
  130. auth: stream.parse()?,
  131. },
  132. )),
  133. _ => return Err(ParseError::new(ident.span(), "Invalid attribute")),
  134. }
  135. }
  136. "associated_token" => {
  137. stream.parse::<Token![:]>()?;
  138. stream.parse::<Token![:]>()?;
  139. let kw = stream.call(Ident::parse_any)?.to_string();
  140. stream.parse::<Token![=]>()?;
  141. let span = ident
  142. .span()
  143. .join(stream.span())
  144. .unwrap_or_else(|| ident.span());
  145. match kw.as_str() {
  146. "mint" => ConstraintToken::AssociatedTokenMint(Context::new(
  147. span,
  148. ConstraintTokenMint {
  149. mint: stream.parse()?,
  150. },
  151. )),
  152. "authority" => ConstraintToken::AssociatedTokenAuthority(Context::new(
  153. span,
  154. ConstraintTokenAuthority {
  155. auth: stream.parse()?,
  156. },
  157. )),
  158. _ => return Err(ParseError::new(ident.span(), "Invalid attribute")),
  159. }
  160. }
  161. "bump" => {
  162. let bump = {
  163. if stream.peek(Token![=]) {
  164. stream.parse::<Token![=]>()?;
  165. Some(stream.parse()?)
  166. } else {
  167. None
  168. }
  169. };
  170. ConstraintToken::Bump(Context::new(ident.span(), ConstraintTokenBump { bump }))
  171. }
  172. "seeds" => {
  173. if stream.peek(Token![:]) {
  174. stream.parse::<Token![:]>()?;
  175. stream.parse::<Token![:]>()?;
  176. let kw = stream.call(Ident::parse_any)?.to_string();
  177. stream.parse::<Token![=]>()?;
  178. let span = ident
  179. .span()
  180. .join(stream.span())
  181. .unwrap_or_else(|| ident.span());
  182. match kw.as_str() {
  183. "program" => ConstraintToken::ProgramSeed(Context::new(
  184. span,
  185. ConstraintProgramSeed {
  186. program_seed: stream.parse()?,
  187. },
  188. )),
  189. _ => return Err(ParseError::new(ident.span(), "Invalid attribute")),
  190. }
  191. } else {
  192. stream.parse::<Token![=]>()?;
  193. let span = ident
  194. .span()
  195. .join(stream.span())
  196. .unwrap_or_else(|| ident.span());
  197. let seeds;
  198. let bracket = bracketed!(seeds in stream);
  199. ConstraintToken::Seeds(Context::new(
  200. span.join(bracket.span).unwrap_or(span),
  201. ConstraintSeeds {
  202. seeds: seeds.parse_terminated(Expr::parse)?,
  203. },
  204. ))
  205. }
  206. }
  207. _ => {
  208. stream.parse::<Token![=]>()?;
  209. let span = ident
  210. .span()
  211. .join(stream.span())
  212. .unwrap_or_else(|| ident.span());
  213. match kw.as_str() {
  214. "has_one" => ConstraintToken::HasOne(Context::new(
  215. span,
  216. ConstraintHasOne {
  217. join_target: stream.parse()?,
  218. error: parse_optional_custom_error(&stream)?,
  219. },
  220. )),
  221. "owner" => ConstraintToken::Owner(Context::new(
  222. span,
  223. ConstraintOwner {
  224. owner_address: stream.parse()?,
  225. error: parse_optional_custom_error(&stream)?,
  226. },
  227. )),
  228. "rent_exempt" => ConstraintToken::RentExempt(Context::new(
  229. span,
  230. match stream.parse::<Ident>()?.to_string().as_str() {
  231. "skip" => ConstraintRentExempt::Skip,
  232. "enforce" => ConstraintRentExempt::Enforce,
  233. _ => {
  234. return Err(ParseError::new(
  235. span,
  236. "rent_exempt must be either skip or enforce",
  237. ))
  238. }
  239. },
  240. )),
  241. "state" => ConstraintToken::State(Context::new(
  242. span,
  243. ConstraintState {
  244. program_target: stream.parse()?,
  245. },
  246. )),
  247. "payer" => ConstraintToken::Payer(Context::new(
  248. span,
  249. ConstraintPayer {
  250. target: stream.parse()?,
  251. },
  252. )),
  253. "space" => ConstraintToken::Space(Context::new(
  254. span,
  255. ConstraintSpace {
  256. space: stream.parse()?,
  257. },
  258. )),
  259. "constraint" => ConstraintToken::Raw(Context::new(
  260. span,
  261. ConstraintRaw {
  262. raw: stream.parse()?,
  263. error: parse_optional_custom_error(&stream)?,
  264. },
  265. )),
  266. "close" => ConstraintToken::Close(Context::new(
  267. span,
  268. ConstraintClose {
  269. sol_dest: stream.parse()?,
  270. },
  271. )),
  272. "address" => ConstraintToken::Address(Context::new(
  273. span,
  274. ConstraintAddress {
  275. address: stream.parse()?,
  276. error: parse_optional_custom_error(&stream)?,
  277. },
  278. )),
  279. _ => return Err(ParseError::new(ident.span(), "Invalid attribute")),
  280. }
  281. }
  282. };
  283. Ok(c)
  284. }
  285. fn parse_optional_custom_error(stream: &ParseStream) -> ParseResult<Option<Expr>> {
  286. if stream.peek(Token![@]) {
  287. stream.parse::<Token![@]>()?;
  288. stream.parse().map(Some)
  289. } else {
  290. Ok(None)
  291. }
  292. }
  293. #[derive(Default)]
  294. pub struct ConstraintGroupBuilder<'ty> {
  295. pub f_ty: Option<&'ty Ty>,
  296. pub init: Option<Context<ConstraintInit>>,
  297. pub zeroed: Option<Context<ConstraintZeroed>>,
  298. pub mutable: Option<Context<ConstraintMut>>,
  299. pub signer: Option<Context<ConstraintSigner>>,
  300. pub has_one: Vec<Context<ConstraintHasOne>>,
  301. pub literal: Vec<Context<ConstraintLiteral>>,
  302. pub raw: Vec<Context<ConstraintRaw>>,
  303. pub owner: Option<Context<ConstraintOwner>>,
  304. pub rent_exempt: Option<Context<ConstraintRentExempt>>,
  305. pub seeds: Option<Context<ConstraintSeeds>>,
  306. pub executable: Option<Context<ConstraintExecutable>>,
  307. pub state: Option<Context<ConstraintState>>,
  308. pub payer: Option<Context<ConstraintPayer>>,
  309. pub space: Option<Context<ConstraintSpace>>,
  310. pub close: Option<Context<ConstraintClose>>,
  311. pub address: Option<Context<ConstraintAddress>>,
  312. pub token_mint: Option<Context<ConstraintTokenMint>>,
  313. pub token_authority: Option<Context<ConstraintTokenAuthority>>,
  314. pub associated_token_mint: Option<Context<ConstraintTokenMint>>,
  315. pub associated_token_authority: Option<Context<ConstraintTokenAuthority>>,
  316. pub mint_authority: Option<Context<ConstraintMintAuthority>>,
  317. pub mint_freeze_authority: Option<Context<ConstraintMintFreezeAuthority>>,
  318. pub mint_decimals: Option<Context<ConstraintMintDecimals>>,
  319. pub bump: Option<Context<ConstraintTokenBump>>,
  320. pub program_seed: Option<Context<ConstraintProgramSeed>>,
  321. }
  322. impl<'ty> ConstraintGroupBuilder<'ty> {
  323. pub fn new(f_ty: Option<&'ty Ty>) -> Self {
  324. Self {
  325. f_ty,
  326. init: None,
  327. zeroed: None,
  328. mutable: None,
  329. signer: None,
  330. has_one: Vec::new(),
  331. literal: Vec::new(),
  332. raw: Vec::new(),
  333. owner: None,
  334. rent_exempt: None,
  335. seeds: None,
  336. executable: None,
  337. state: None,
  338. payer: None,
  339. space: None,
  340. close: None,
  341. address: None,
  342. token_mint: None,
  343. token_authority: None,
  344. associated_token_mint: None,
  345. associated_token_authority: None,
  346. mint_authority: None,
  347. mint_freeze_authority: None,
  348. mint_decimals: None,
  349. bump: None,
  350. program_seed: None,
  351. }
  352. }
  353. pub fn build(mut self) -> ParseResult<ConstraintGroup> {
  354. // Init.
  355. if let Some(i) = &self.init {
  356. if cfg!(not(feature = "init-if-needed")) && i.if_needed {
  357. return Err(ParseError::new(
  358. i.span(),
  359. "init_if_needed requires that anchor-lang be imported \
  360. with the init-if-needed cargo feature enabled. \
  361. Carefully read the init_if_needed docs before using this feature \
  362. to make sure you know how to protect yourself against \
  363. re-initialization attacks.",
  364. ));
  365. }
  366. match self.mutable {
  367. Some(m) => {
  368. return Err(ParseError::new(
  369. m.span(),
  370. "mut cannot be provided with init",
  371. ))
  372. }
  373. None => self
  374. .mutable
  375. .replace(Context::new(i.span(), ConstraintMut { error: None })),
  376. };
  377. // Rent exempt if not explicitly skipped.
  378. if self.rent_exempt.is_none() {
  379. self.rent_exempt
  380. .replace(Context::new(i.span(), ConstraintRentExempt::Enforce));
  381. }
  382. if self.payer.is_none() {
  383. return Err(ParseError::new(
  384. i.span(),
  385. "payer must be provided when initializing an account",
  386. ));
  387. }
  388. // When initializing a non-PDA account, the account being
  389. // initialized must sign to invoke the system program's create
  390. // account instruction.
  391. if self.signer.is_none() && self.seeds.is_none() && self.associated_token_mint.is_none()
  392. {
  393. self.signer
  394. .replace(Context::new(i.span(), ConstraintSigner { error: None }));
  395. }
  396. }
  397. // Zero.
  398. if let Some(z) = &self.zeroed {
  399. match self.mutable {
  400. Some(m) => {
  401. return Err(ParseError::new(
  402. m.span(),
  403. "mut cannot be provided with zeroed",
  404. ))
  405. }
  406. None => self
  407. .mutable
  408. .replace(Context::new(z.span(), ConstraintMut { error: None })),
  409. };
  410. // Rent exempt if not explicitly skipped.
  411. if self.rent_exempt.is_none() {
  412. self.rent_exempt
  413. .replace(Context::new(z.span(), ConstraintRentExempt::Enforce));
  414. }
  415. }
  416. // Seeds.
  417. if let Some(i) = &self.seeds {
  418. if self.init.is_some() && self.payer.is_none() {
  419. return Err(ParseError::new(
  420. i.span(),
  421. "payer must be provided when creating a program derived address",
  422. ));
  423. }
  424. if self.bump.is_none() {
  425. return Err(ParseError::new(
  426. i.span(),
  427. "bump must be provided with seeds",
  428. ));
  429. }
  430. }
  431. // Token.
  432. if let Some(token_mint) = &self.token_mint {
  433. if self.token_authority.is_none() {
  434. return Err(ParseError::new(
  435. token_mint.span(),
  436. "token authority must be provided if token mint is",
  437. ));
  438. }
  439. if self.init.is_none() {
  440. return Err(ParseError::new(
  441. token_mint.span(),
  442. "init is required for a pda token",
  443. ));
  444. }
  445. }
  446. if let Some(token_authority) = &self.token_authority {
  447. if self.token_mint.is_none() {
  448. return Err(ParseError::new(
  449. token_authority.span(),
  450. "token mint must be provided if token authority is",
  451. ));
  452. }
  453. }
  454. // Mint.
  455. if let Some(mint_decimals) = &self.mint_decimals {
  456. if self.mint_authority.is_none() {
  457. return Err(ParseError::new(
  458. mint_decimals.span(),
  459. "mint authority must be provided if mint decimals is",
  460. ));
  461. }
  462. }
  463. if let Some(mint_authority) = &self.mint_authority {
  464. if self.mint_decimals.is_none() {
  465. return Err(ParseError::new(
  466. mint_authority.span(),
  467. "mint decimals must be provided if mint authority is",
  468. ));
  469. }
  470. }
  471. // SPL Space.
  472. if self.init.is_some()
  473. && self.seeds.is_some()
  474. && self.token_mint.is_some()
  475. && (self.mint_authority.is_some() || self.token_authority.is_some())
  476. && self.space.is_some()
  477. {
  478. return Err(ParseError::new(
  479. self.space.as_ref().unwrap().span(),
  480. "space is not required for initializing an spl account",
  481. ));
  482. }
  483. let ConstraintGroupBuilder {
  484. f_ty: _,
  485. init,
  486. zeroed,
  487. mutable,
  488. signer,
  489. has_one,
  490. literal,
  491. raw,
  492. owner,
  493. rent_exempt,
  494. seeds,
  495. executable,
  496. state,
  497. payer,
  498. space,
  499. close,
  500. address,
  501. token_mint,
  502. token_authority,
  503. associated_token_mint,
  504. associated_token_authority,
  505. mint_authority,
  506. mint_freeze_authority,
  507. mint_decimals,
  508. bump,
  509. program_seed,
  510. } = self;
  511. // Converts Option<Context<T>> -> Option<T>.
  512. macro_rules! into_inner {
  513. ($opt:ident) => {
  514. $opt.map(|c| c.into_inner())
  515. };
  516. ($opt:expr) => {
  517. $opt.map(|c| c.into_inner())
  518. };
  519. }
  520. // Converts Vec<Context<T>> - Vec<T>.
  521. macro_rules! into_inner_vec {
  522. ($opt:ident) => {
  523. $opt.into_iter().map(|c| c.into_inner()).collect()
  524. };
  525. }
  526. let is_init = init.is_some();
  527. let seeds = seeds.map(|c| ConstraintSeedsGroup {
  528. is_init,
  529. seeds: c.seeds.clone(),
  530. bump: into_inner!(bump)
  531. .map(|b| b.bump)
  532. .expect("bump must be provided with seeds"),
  533. program_seed: into_inner!(program_seed).map(|id| id.program_seed),
  534. });
  535. let associated_token = match (associated_token_mint, associated_token_authority) {
  536. (Some(mint), Some(auth)) => Some(ConstraintAssociatedToken {
  537. wallet: auth.into_inner().auth,
  538. mint: mint.into_inner().mint,
  539. }),
  540. (Some(mint), None) => return Err(ParseError::new(
  541. mint.span(),
  542. "authority must be provided to specify an associated token program derived address",
  543. )),
  544. (None, Some(auth)) => {
  545. return Err(ParseError::new(
  546. auth.span(),
  547. "mint must be provided to specify an associated token program derived address",
  548. ))
  549. }
  550. _ => None,
  551. };
  552. Ok(ConstraintGroup {
  553. init: init.as_ref().map(|i| Ok(ConstraintInitGroup {
  554. if_needed: i.if_needed,
  555. seeds: seeds.clone(),
  556. payer: into_inner!(payer.clone()).map(|a| a.target),
  557. space: space.clone().map(|s| s.space.clone()),
  558. kind: if let Some(tm) = &token_mint {
  559. InitKind::Token {
  560. mint: tm.clone().into_inner().mint,
  561. owner: match &token_authority {
  562. Some(a) => a.clone().into_inner().auth,
  563. None => return Err(ParseError::new(
  564. tm.span(),
  565. "authority must be provided to initialize a token program derived address"
  566. )),
  567. },
  568. }
  569. } else if let Some(at) = &associated_token {
  570. InitKind::AssociatedToken {
  571. mint: at.mint.clone(),
  572. owner: at.wallet.clone()
  573. }
  574. } else if let Some(d) = &mint_decimals {
  575. InitKind::Mint {
  576. decimals: d.clone().into_inner().decimals,
  577. owner: match &mint_authority {
  578. Some(a) => a.clone().into_inner().mint_auth,
  579. None => return Err(ParseError::new(
  580. d.span(),
  581. "authority must be provided to initialize a mint program derived address"
  582. ))
  583. },
  584. freeze_authority: mint_freeze_authority.map(|fa| fa.into_inner().mint_freeze_auth)
  585. }
  586. } else {
  587. InitKind::Program {
  588. owner: owner.as_ref().map(|o| o.owner_address.clone()),
  589. }
  590. },
  591. })).transpose()?,
  592. zeroed: into_inner!(zeroed),
  593. mutable: into_inner!(mutable),
  594. signer: into_inner!(signer),
  595. has_one: into_inner_vec!(has_one),
  596. literal: into_inner_vec!(literal),
  597. raw: into_inner_vec!(raw),
  598. owner: into_inner!(owner),
  599. rent_exempt: into_inner!(rent_exempt),
  600. executable: into_inner!(executable),
  601. state: into_inner!(state),
  602. close: into_inner!(close),
  603. address: into_inner!(address),
  604. associated_token: if !is_init { associated_token } else { None },
  605. seeds,
  606. })
  607. }
  608. pub fn add(&mut self, c: ConstraintToken) -> ParseResult<()> {
  609. match c {
  610. ConstraintToken::Init(c) => self.add_init(c),
  611. ConstraintToken::Zeroed(c) => self.add_zeroed(c),
  612. ConstraintToken::Mut(c) => self.add_mut(c),
  613. ConstraintToken::Signer(c) => self.add_signer(c),
  614. ConstraintToken::HasOne(c) => self.add_has_one(c),
  615. ConstraintToken::Literal(c) => self.add_literal(c),
  616. ConstraintToken::Raw(c) => self.add_raw(c),
  617. ConstraintToken::Owner(c) => self.add_owner(c),
  618. ConstraintToken::RentExempt(c) => self.add_rent_exempt(c),
  619. ConstraintToken::Seeds(c) => self.add_seeds(c),
  620. ConstraintToken::Executable(c) => self.add_executable(c),
  621. ConstraintToken::State(c) => self.add_state(c),
  622. ConstraintToken::Payer(c) => self.add_payer(c),
  623. ConstraintToken::Space(c) => self.add_space(c),
  624. ConstraintToken::Close(c) => self.add_close(c),
  625. ConstraintToken::Address(c) => self.add_address(c),
  626. ConstraintToken::TokenAuthority(c) => self.add_token_authority(c),
  627. ConstraintToken::TokenMint(c) => self.add_token_mint(c),
  628. ConstraintToken::AssociatedTokenAuthority(c) => self.add_associated_token_authority(c),
  629. ConstraintToken::AssociatedTokenMint(c) => self.add_associated_token_mint(c),
  630. ConstraintToken::MintAuthority(c) => self.add_mint_authority(c),
  631. ConstraintToken::MintFreezeAuthority(c) => self.add_mint_freeze_authority(c),
  632. ConstraintToken::MintDecimals(c) => self.add_mint_decimals(c),
  633. ConstraintToken::Bump(c) => self.add_bump(c),
  634. ConstraintToken::ProgramSeed(c) => self.add_program_seed(c),
  635. }
  636. }
  637. fn add_init(&mut self, c: Context<ConstraintInit>) -> ParseResult<()> {
  638. if self.init.is_some() {
  639. return Err(ParseError::new(c.span(), "init already provided"));
  640. }
  641. if self.zeroed.is_some() {
  642. return Err(ParseError::new(c.span(), "zeroed already provided"));
  643. }
  644. self.init.replace(c);
  645. Ok(())
  646. }
  647. fn add_zeroed(&mut self, c: Context<ConstraintZeroed>) -> ParseResult<()> {
  648. if self.zeroed.is_some() {
  649. return Err(ParseError::new(c.span(), "zeroed already provided"));
  650. }
  651. if self.init.is_some() {
  652. return Err(ParseError::new(c.span(), "init already provided"));
  653. }
  654. self.zeroed.replace(c);
  655. Ok(())
  656. }
  657. fn add_close(&mut self, c: Context<ConstraintClose>) -> ParseResult<()> {
  658. if !matches!(self.f_ty, Some(Ty::ProgramAccount(_)))
  659. && !matches!(self.f_ty, Some(Ty::Account(_)))
  660. && !matches!(self.f_ty, Some(Ty::Loader(_)))
  661. && !matches!(self.f_ty, Some(Ty::AccountLoader(_)))
  662. {
  663. return Err(ParseError::new(
  664. c.span(),
  665. "close must be on an Account, ProgramAccount, or Loader",
  666. ));
  667. }
  668. if self.mutable.is_none() {
  669. return Err(ParseError::new(
  670. c.span(),
  671. "mut must be provided before close",
  672. ));
  673. }
  674. if self.close.is_some() {
  675. return Err(ParseError::new(c.span(), "close already provided"));
  676. }
  677. self.close.replace(c);
  678. Ok(())
  679. }
  680. fn add_address(&mut self, c: Context<ConstraintAddress>) -> ParseResult<()> {
  681. if self.address.is_some() {
  682. return Err(ParseError::new(c.span(), "address already provided"));
  683. }
  684. self.address.replace(c);
  685. Ok(())
  686. }
  687. fn add_token_mint(&mut self, c: Context<ConstraintTokenMint>) -> ParseResult<()> {
  688. if self.token_mint.is_some() {
  689. return Err(ParseError::new(c.span(), "token mint already provided"));
  690. }
  691. if self.associated_token_mint.is_some() {
  692. return Err(ParseError::new(
  693. c.span(),
  694. "associated token mint already provided",
  695. ));
  696. }
  697. if self.init.is_none() {
  698. return Err(ParseError::new(
  699. c.span(),
  700. "init must be provided before token",
  701. ));
  702. }
  703. self.token_mint.replace(c);
  704. Ok(())
  705. }
  706. fn add_associated_token_mint(&mut self, c: Context<ConstraintTokenMint>) -> ParseResult<()> {
  707. if self.associated_token_mint.is_some() {
  708. return Err(ParseError::new(
  709. c.span(),
  710. "associated token mint already provided",
  711. ));
  712. }
  713. if self.token_mint.is_some() {
  714. return Err(ParseError::new(c.span(), "token mint already provided"));
  715. }
  716. self.associated_token_mint.replace(c);
  717. Ok(())
  718. }
  719. fn add_bump(&mut self, c: Context<ConstraintTokenBump>) -> ParseResult<()> {
  720. if self.bump.is_some() {
  721. return Err(ParseError::new(c.span(), "bump already provided"));
  722. }
  723. if self.seeds.is_none() {
  724. return Err(ParseError::new(
  725. c.span(),
  726. "seeds must be provided before bump",
  727. ));
  728. }
  729. self.bump.replace(c);
  730. Ok(())
  731. }
  732. fn add_program_seed(&mut self, c: Context<ConstraintProgramSeed>) -> ParseResult<()> {
  733. if self.program_seed.is_some() {
  734. return Err(ParseError::new(c.span(), "seeds::program already provided"));
  735. }
  736. if self.seeds.is_none() {
  737. return Err(ParseError::new(
  738. c.span(),
  739. "seeds must be provided before seeds::program",
  740. ));
  741. }
  742. if let Some(ref init) = self.init {
  743. if init.if_needed {
  744. return Err(ParseError::new(
  745. c.span(),
  746. "seeds::program cannot be used with init_if_needed",
  747. ));
  748. } else {
  749. return Err(ParseError::new(
  750. c.span(),
  751. "seeds::program cannot be used with init",
  752. ));
  753. }
  754. }
  755. self.program_seed.replace(c);
  756. Ok(())
  757. }
  758. fn add_token_authority(&mut self, c: Context<ConstraintTokenAuthority>) -> ParseResult<()> {
  759. if self.token_authority.is_some() {
  760. return Err(ParseError::new(
  761. c.span(),
  762. "token authority already provided",
  763. ));
  764. }
  765. if self.init.is_none() {
  766. return Err(ParseError::new(
  767. c.span(),
  768. "init must be provided before token authority",
  769. ));
  770. }
  771. self.token_authority.replace(c);
  772. Ok(())
  773. }
  774. fn add_associated_token_authority(
  775. &mut self,
  776. c: Context<ConstraintTokenAuthority>,
  777. ) -> ParseResult<()> {
  778. if self.associated_token_authority.is_some() {
  779. return Err(ParseError::new(
  780. c.span(),
  781. "associated token authority already provided",
  782. ));
  783. }
  784. if self.token_authority.is_some() {
  785. return Err(ParseError::new(
  786. c.span(),
  787. "token authority already provided",
  788. ));
  789. }
  790. self.associated_token_authority.replace(c);
  791. Ok(())
  792. }
  793. fn add_mint_authority(&mut self, c: Context<ConstraintMintAuthority>) -> ParseResult<()> {
  794. if self.mint_authority.is_some() {
  795. return Err(ParseError::new(c.span(), "mint authority already provided"));
  796. }
  797. if self.init.is_none() {
  798. return Err(ParseError::new(
  799. c.span(),
  800. "init must be provided before mint authority",
  801. ));
  802. }
  803. self.mint_authority.replace(c);
  804. Ok(())
  805. }
  806. fn add_mint_freeze_authority(
  807. &mut self,
  808. c: Context<ConstraintMintFreezeAuthority>,
  809. ) -> ParseResult<()> {
  810. if self.mint_freeze_authority.is_some() {
  811. return Err(ParseError::new(
  812. c.span(),
  813. "mint freeze_authority already provided",
  814. ));
  815. }
  816. if self.init.is_none() {
  817. return Err(ParseError::new(
  818. c.span(),
  819. "init must be provided before mint freeze_authority",
  820. ));
  821. }
  822. self.mint_freeze_authority.replace(c);
  823. Ok(())
  824. }
  825. fn add_mint_decimals(&mut self, c: Context<ConstraintMintDecimals>) -> ParseResult<()> {
  826. if self.mint_decimals.is_some() {
  827. return Err(ParseError::new(c.span(), "mint decimals already provided"));
  828. }
  829. if self.init.is_none() {
  830. return Err(ParseError::new(
  831. c.span(),
  832. "init must be provided before mint decimals",
  833. ));
  834. }
  835. self.mint_decimals.replace(c);
  836. Ok(())
  837. }
  838. fn add_mut(&mut self, c: Context<ConstraintMut>) -> ParseResult<()> {
  839. if self.mutable.is_some() {
  840. return Err(ParseError::new(c.span(), "mut already provided"));
  841. }
  842. self.mutable.replace(c);
  843. Ok(())
  844. }
  845. fn add_signer(&mut self, c: Context<ConstraintSigner>) -> ParseResult<()> {
  846. if self.signer.is_some() {
  847. return Err(ParseError::new(c.span(), "signer already provided"));
  848. }
  849. self.signer.replace(c);
  850. Ok(())
  851. }
  852. fn add_has_one(&mut self, c: Context<ConstraintHasOne>) -> ParseResult<()> {
  853. if self
  854. .has_one
  855. .iter()
  856. .filter(|item| item.join_target == c.join_target)
  857. .count()
  858. > 0
  859. {
  860. return Err(ParseError::new(c.span(), "has_one target already provided"));
  861. }
  862. self.has_one.push(c);
  863. Ok(())
  864. }
  865. fn add_literal(&mut self, c: Context<ConstraintLiteral>) -> ParseResult<()> {
  866. self.literal.push(c);
  867. Ok(())
  868. }
  869. fn add_raw(&mut self, c: Context<ConstraintRaw>) -> ParseResult<()> {
  870. self.raw.push(c);
  871. Ok(())
  872. }
  873. fn add_owner(&mut self, c: Context<ConstraintOwner>) -> ParseResult<()> {
  874. if self.owner.is_some() {
  875. return Err(ParseError::new(c.span(), "owner already provided"));
  876. }
  877. self.owner.replace(c);
  878. Ok(())
  879. }
  880. fn add_rent_exempt(&mut self, c: Context<ConstraintRentExempt>) -> ParseResult<()> {
  881. if self.rent_exempt.is_some() {
  882. return Err(ParseError::new(c.span(), "rent already provided"));
  883. }
  884. self.rent_exempt.replace(c);
  885. Ok(())
  886. }
  887. fn add_seeds(&mut self, c: Context<ConstraintSeeds>) -> ParseResult<()> {
  888. if self.seeds.is_some() {
  889. return Err(ParseError::new(c.span(), "seeds already provided"));
  890. }
  891. self.seeds.replace(c);
  892. Ok(())
  893. }
  894. fn add_executable(&mut self, c: Context<ConstraintExecutable>) -> ParseResult<()> {
  895. if self.executable.is_some() {
  896. return Err(ParseError::new(c.span(), "executable already provided"));
  897. }
  898. self.executable.replace(c);
  899. Ok(())
  900. }
  901. fn add_state(&mut self, c: Context<ConstraintState>) -> ParseResult<()> {
  902. if self.state.is_some() {
  903. return Err(ParseError::new(c.span(), "state already provided"));
  904. }
  905. self.state.replace(c);
  906. Ok(())
  907. }
  908. fn add_payer(&mut self, c: Context<ConstraintPayer>) -> ParseResult<()> {
  909. if self.init.is_none() {
  910. return Err(ParseError::new(
  911. c.span(),
  912. "init must be provided before payer",
  913. ));
  914. }
  915. if self.payer.is_some() {
  916. return Err(ParseError::new(c.span(), "payer already provided"));
  917. }
  918. self.payer.replace(c);
  919. Ok(())
  920. }
  921. fn add_space(&mut self, c: Context<ConstraintSpace>) -> ParseResult<()> {
  922. if self.init.is_none() {
  923. return Err(ParseError::new(
  924. c.span(),
  925. "init must be provided before space",
  926. ));
  927. }
  928. if self.space.is_some() {
  929. return Err(ParseError::new(c.span(), "space already provided"));
  930. }
  931. self.space.replace(c);
  932. Ok(())
  933. }
  934. }