lang: allow `token::...` and `mint::...` to be used as checks without init (#1505)
Co-authored-by: Paul Schaaf <paulsimonschaaf@gmail.com>
This commit is contained in:
parent
537d470954
commit
f5dffe6490
|
@ -436,8 +436,9 @@ use syn::parse_macro_input;
|
|||
/// <code>#[account(token::mint = <target_account>, token::authority = <target_account>)]</code>
|
||||
/// </td>
|
||||
/// <td>
|
||||
/// Can currently only be used with <code>init</code> to create a token
|
||||
/// account with the given mint address and authority.
|
||||
/// Can be used as a check or with <code>init</code> to create a token
|
||||
/// account with the given mint address and authority.<br>
|
||||
/// When used as a check, it's possible to only specify a subset of the constraints.
|
||||
/// <br><br>
|
||||
/// Example:
|
||||
/// <pre>
|
||||
|
@ -466,9 +467,10 @@ use syn::parse_macro_input;
|
|||
/// <code>#[account(mint::authority = <target_account>, mint::decimals = <expr>, mint::freeze_authority = <target_account>)]</code>
|
||||
/// </td>
|
||||
/// <td>
|
||||
/// Can currently only be used with <code>init</code> to create a mint
|
||||
/// Can be used as a check or with <code>init</code> to create a mint
|
||||
/// account with the given mint decimals and mint authority.<br>
|
||||
/// The freeze authority is optional.
|
||||
/// The freeze authority is optional when used with <code>init</code>.<br>
|
||||
/// When used as a check, it's possible to only specify a subset of the constraints.
|
||||
/// <br><br>
|
||||
/// Example:
|
||||
/// <pre>
|
||||
|
|
|
@ -57,6 +57,8 @@ pub fn linearize(c_group: &ConstraintGroup) -> Vec<Constraint> {
|
|||
close,
|
||||
address,
|
||||
associated_token,
|
||||
token_account,
|
||||
mint,
|
||||
} = c_group.clone();
|
||||
|
||||
let mut constraints = Vec::new();
|
||||
|
@ -100,6 +102,12 @@ pub fn linearize(c_group: &ConstraintGroup) -> Vec<Constraint> {
|
|||
if let Some(c) = address {
|
||||
constraints.push(Constraint::Address(c));
|
||||
}
|
||||
if let Some(c) = token_account {
|
||||
constraints.push(Constraint::TokenAccount(c));
|
||||
}
|
||||
if let Some(c) = mint {
|
||||
constraints.push(Constraint::Mint(c));
|
||||
}
|
||||
constraints
|
||||
}
|
||||
|
||||
|
@ -120,6 +128,8 @@ fn generate_constraint(f: &Field, c: &Constraint) -> proc_macro2::TokenStream {
|
|||
Constraint::Close(c) => generate_constraint_close(f, c),
|
||||
Constraint::Address(c) => generate_constraint_address(f, c),
|
||||
Constraint::AssociatedToken(c) => generate_constraint_associated_token(f, c),
|
||||
Constraint::TokenAccount(c) => generate_constraint_token_account(f, c),
|
||||
Constraint::Mint(c) => generate_constraint_mint(f, c),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -682,6 +692,63 @@ fn generate_constraint_associated_token(
|
|||
}
|
||||
}
|
||||
|
||||
fn generate_constraint_token_account(
|
||||
f: &Field,
|
||||
c: &ConstraintTokenAccountGroup,
|
||||
) -> proc_macro2::TokenStream {
|
||||
let name = &f.ident;
|
||||
let authority_check = match &c.authority {
|
||||
Some(authority) => {
|
||||
quote! { if #name.owner != #authority.key() { return Err(anchor_lang::error::ErrorCode::ConstraintTokenOwner.into()); } }
|
||||
}
|
||||
None => quote! {},
|
||||
};
|
||||
let mint_check = match &c.mint {
|
||||
Some(mint) => {
|
||||
quote! { if #name.mint != #mint.key() { return Err(anchor_lang::error::ErrorCode::ConstraintTokenMint.into()); } }
|
||||
}
|
||||
None => quote! {},
|
||||
};
|
||||
quote! {
|
||||
#authority_check
|
||||
#mint_check
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_constraint_mint(f: &Field, c: &ConstraintTokenMintGroup) -> proc_macro2::TokenStream {
|
||||
let name = &f.ident;
|
||||
|
||||
let decimal_check = match &c.decimals {
|
||||
Some(decimals) => quote! {
|
||||
if #name.decimals != #decimals {
|
||||
return Err(anchor_lang::error::ErrorCode::ConstraintMintDecimals.into());
|
||||
}
|
||||
},
|
||||
None => quote! {},
|
||||
};
|
||||
let mint_authority_check = match &c.mint_authority {
|
||||
Some(mint_authority) => quote! {
|
||||
if #name.mint_authority != anchor_lang::solana_program::program_option::COption::Some(anchor_lang::Key::key(&#mint_authority)) {
|
||||
return Err(anchor_lang::error::ErrorCode::ConstraintMintMintAuthority.into());
|
||||
}
|
||||
},
|
||||
None => quote! {},
|
||||
};
|
||||
let freeze_authority_check = match &c.freeze_authority {
|
||||
Some(freeze_authority) => quote! {
|
||||
if #name.freeze_authority != anchor_lang::solana_program::program_option::COption::Some(anchor_lang::Key::key(&#freeze_authority)) {
|
||||
return Err(anchor_lang::error::ErrorCode::ConstraintMintFreezeAuthority.into());
|
||||
}
|
||||
},
|
||||
None => quote! {},
|
||||
};
|
||||
quote! {
|
||||
#decimal_check
|
||||
#mint_authority_check
|
||||
#freeze_authority_check
|
||||
}
|
||||
}
|
||||
|
||||
// Generated code to create an account with with system program with the
|
||||
// given `space` amount of data, owned by `owner`.
|
||||
//
|
||||
|
|
|
@ -587,6 +587,8 @@ pub struct ConstraintGroup {
|
|||
close: Option<ConstraintClose>,
|
||||
address: Option<ConstraintAddress>,
|
||||
associated_token: Option<ConstraintAssociatedToken>,
|
||||
token_account: Option<ConstraintTokenAccountGroup>,
|
||||
mint: Option<ConstraintTokenMintGroup>,
|
||||
}
|
||||
|
||||
impl ConstraintGroup {
|
||||
|
@ -628,6 +630,8 @@ pub enum Constraint {
|
|||
State(ConstraintState),
|
||||
Close(ConstraintClose),
|
||||
Address(ConstraintAddress),
|
||||
TokenAccount(ConstraintTokenAccountGroup),
|
||||
Mint(ConstraintTokenMintGroup),
|
||||
}
|
||||
|
||||
// Constraint token is a single keyword in a `#[account(<TOKEN>)]` attribute.
|
||||
|
@ -832,6 +836,19 @@ pub struct ConstraintAssociatedToken {
|
|||
pub mint: Expr,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ConstraintTokenAccountGroup {
|
||||
pub mint: Option<Expr>,
|
||||
pub authority: Option<Expr>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ConstraintTokenMintGroup {
|
||||
pub decimals: Option<Expr>,
|
||||
pub mint_authority: Option<Expr>,
|
||||
pub freeze_authority: Option<Expr>,
|
||||
}
|
||||
|
||||
// Syntaxt context object for preserving metadata about the inner item.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Context<T> {
|
||||
|
|
|
@ -424,6 +424,42 @@ impl<'ty> ConstraintGroupBuilder<'ty> {
|
|||
));
|
||||
}
|
||||
}
|
||||
|
||||
// TokenAccount.
|
||||
if let Some(token_mint) = &self.token_mint {
|
||||
if self.token_authority.is_none() {
|
||||
return Err(ParseError::new(
|
||||
token_mint.span(),
|
||||
"when initializing, token authority must be provided if token mint is",
|
||||
));
|
||||
}
|
||||
}
|
||||
if let Some(token_authority) = &self.token_authority {
|
||||
if self.token_mint.is_none() {
|
||||
return Err(ParseError::new(
|
||||
token_authority.span(),
|
||||
"when initializing, token mint must be provided if token authority is",
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// Mint.
|
||||
if let Some(mint_decimals) = &self.mint_decimals {
|
||||
if self.mint_authority.is_none() {
|
||||
return Err(ParseError::new(
|
||||
mint_decimals.span(),
|
||||
"when initializing, mint authority must be provided if mint decimals is",
|
||||
));
|
||||
}
|
||||
}
|
||||
if let Some(mint_authority) = &self.mint_authority {
|
||||
if self.mint_decimals.is_none() {
|
||||
return Err(ParseError::new(
|
||||
mint_authority.span(),
|
||||
"when initializing, mint decimals must be provided if mint authority is",
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Zero.
|
||||
|
@ -462,49 +498,6 @@ impl<'ty> ConstraintGroupBuilder<'ty> {
|
|||
}
|
||||
}
|
||||
|
||||
// Token.
|
||||
if let Some(token_mint) = &self.token_mint {
|
||||
if self.token_authority.is_none() {
|
||||
return Err(ParseError::new(
|
||||
token_mint.span(),
|
||||
"token authority must be provided if token mint is",
|
||||
));
|
||||
}
|
||||
|
||||
if self.init.is_none() {
|
||||
return Err(ParseError::new(
|
||||
token_mint.span(),
|
||||
"init is required for a pda token",
|
||||
));
|
||||
}
|
||||
}
|
||||
if let Some(token_authority) = &self.token_authority {
|
||||
if self.token_mint.is_none() {
|
||||
return Err(ParseError::new(
|
||||
token_authority.span(),
|
||||
"token mint must be provided if token authority is",
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// Mint.
|
||||
if let Some(mint_decimals) = &self.mint_decimals {
|
||||
if self.mint_authority.is_none() {
|
||||
return Err(ParseError::new(
|
||||
mint_decimals.span(),
|
||||
"mint authority must be provided if mint decimals is",
|
||||
));
|
||||
}
|
||||
}
|
||||
if let Some(mint_authority) = &self.mint_authority {
|
||||
if self.mint_decimals.is_none() {
|
||||
return Err(ParseError::new(
|
||||
mint_authority.span(),
|
||||
"mint decimals must be provided if mint authority is",
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// Space.
|
||||
if let Some(i) = &self.init {
|
||||
let initializing_token_program_acc = self.token_mint.is_some()
|
||||
|
@ -600,6 +593,31 @@ impl<'ty> ConstraintGroupBuilder<'ty> {
|
|||
}
|
||||
_ => None,
|
||||
};
|
||||
let token_account = match (&token_mint, &token_authority) {
|
||||
(None, None) => None,
|
||||
_ => Some(ConstraintTokenAccountGroup {
|
||||
mint: token_mint.as_ref().map(|a| a.clone().into_inner().mint),
|
||||
authority: token_authority
|
||||
.as_ref()
|
||||
.map(|a| a.clone().into_inner().auth),
|
||||
}),
|
||||
};
|
||||
|
||||
let mint = match (&mint_decimals, &mint_authority, &mint_freeze_authority) {
|
||||
(None, None, None) => None,
|
||||
_ => Some(ConstraintTokenMintGroup {
|
||||
decimals: mint_decimals
|
||||
.as_ref()
|
||||
.map(|a| a.clone().into_inner().decimals),
|
||||
mint_authority: mint_authority
|
||||
.as_ref()
|
||||
.map(|a| a.clone().into_inner().mint_auth),
|
||||
freeze_authority: mint_freeze_authority
|
||||
.as_ref()
|
||||
.map(|a| a.clone().into_inner().mint_freeze_auth),
|
||||
}),
|
||||
};
|
||||
|
||||
Ok(ConstraintGroup {
|
||||
init: init.as_ref().map(|i| Ok(ConstraintInitGroup {
|
||||
if_needed: i.if_needed,
|
||||
|
@ -654,6 +672,8 @@ impl<'ty> ConstraintGroupBuilder<'ty> {
|
|||
address: into_inner!(address),
|
||||
associated_token: if !is_init { associated_token } else { None },
|
||||
seeds,
|
||||
token_account: if !is_init {token_account} else {None},
|
||||
mint: if !is_init {mint} else {None},
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -694,6 +714,48 @@ impl<'ty> ConstraintGroupBuilder<'ty> {
|
|||
if self.zeroed.is_some() {
|
||||
return Err(ParseError::new(c.span(), "zeroed already provided"));
|
||||
}
|
||||
if self.token_mint.is_some() {
|
||||
return Err(ParseError::new(
|
||||
c.span(),
|
||||
"init must be provided before token mint",
|
||||
));
|
||||
}
|
||||
if self.token_authority.is_some() {
|
||||
return Err(ParseError::new(
|
||||
c.span(),
|
||||
"init must be provided before token authority",
|
||||
));
|
||||
}
|
||||
if self.mint_authority.is_some() {
|
||||
return Err(ParseError::new(
|
||||
c.span(),
|
||||
"init must be provided before mint authority",
|
||||
));
|
||||
}
|
||||
if self.mint_freeze_authority.is_some() {
|
||||
return Err(ParseError::new(
|
||||
c.span(),
|
||||
"init must be provided before mint freeze authority",
|
||||
));
|
||||
}
|
||||
if self.mint_decimals.is_some() {
|
||||
return Err(ParseError::new(
|
||||
c.span(),
|
||||
"init must be provided before mint decimals",
|
||||
));
|
||||
}
|
||||
if self.associated_token_mint.is_some() {
|
||||
return Err(ParseError::new(
|
||||
c.span(),
|
||||
"init must be provided before associated token mint",
|
||||
));
|
||||
}
|
||||
if self.associated_token_authority.is_some() {
|
||||
return Err(ParseError::new(
|
||||
c.span(),
|
||||
"init must be provided before associated token authority",
|
||||
));
|
||||
}
|
||||
self.init.replace(c);
|
||||
Ok(())
|
||||
}
|
||||
|
@ -751,12 +813,6 @@ impl<'ty> ConstraintGroupBuilder<'ty> {
|
|||
"associated token mint already provided",
|
||||
));
|
||||
}
|
||||
if self.init.is_none() {
|
||||
return Err(ParseError::new(
|
||||
c.span(),
|
||||
"init must be provided before token",
|
||||
));
|
||||
}
|
||||
self.token_mint.replace(c);
|
||||
Ok(())
|
||||
}
|
||||
|
@ -823,12 +879,6 @@ impl<'ty> ConstraintGroupBuilder<'ty> {
|
|||
"token authority already provided",
|
||||
));
|
||||
}
|
||||
if self.init.is_none() {
|
||||
return Err(ParseError::new(
|
||||
c.span(),
|
||||
"init must be provided before token authority",
|
||||
));
|
||||
}
|
||||
self.token_authority.replace(c);
|
||||
Ok(())
|
||||
}
|
||||
|
@ -857,12 +907,6 @@ impl<'ty> ConstraintGroupBuilder<'ty> {
|
|||
if self.mint_authority.is_some() {
|
||||
return Err(ParseError::new(c.span(), "mint authority already provided"));
|
||||
}
|
||||
if self.init.is_none() {
|
||||
return Err(ParseError::new(
|
||||
c.span(),
|
||||
"init must be provided before mint authority",
|
||||
));
|
||||
}
|
||||
self.mint_authority.replace(c);
|
||||
Ok(())
|
||||
}
|
||||
|
@ -877,12 +921,6 @@ impl<'ty> ConstraintGroupBuilder<'ty> {
|
|||
"mint freeze_authority already provided",
|
||||
));
|
||||
}
|
||||
if self.init.is_none() {
|
||||
return Err(ParseError::new(
|
||||
c.span(),
|
||||
"init must be provided before mint freeze_authority",
|
||||
));
|
||||
}
|
||||
self.mint_freeze_authority.replace(c);
|
||||
Ok(())
|
||||
}
|
||||
|
@ -891,12 +929,6 @@ impl<'ty> ConstraintGroupBuilder<'ty> {
|
|||
if self.mint_decimals.is_some() {
|
||||
return Err(ParseError::new(c.span(), "mint decimals already provided"));
|
||||
}
|
||||
if self.init.is_none() {
|
||||
return Err(ParseError::new(
|
||||
c.span(),
|
||||
"init must be provided before mint decimals",
|
||||
));
|
||||
}
|
||||
self.mint_decimals.replace(c);
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@ pub struct TestTokenSeedsInit<'info> {
|
|||
payer = authority,
|
||||
mint::decimals = 6,
|
||||
mint::authority = authority,
|
||||
|
||||
)]
|
||||
pub mint: Account<'info, Mint>,
|
||||
#[account(
|
||||
|
@ -26,7 +25,6 @@ pub struct TestTokenSeedsInit<'info> {
|
|||
payer = authority,
|
||||
token::mint = mint,
|
||||
token::authority = authority,
|
||||
|
||||
)]
|
||||
pub my_pda: Account<'info, TokenAccount>,
|
||||
#[account(mut)]
|
||||
|
@ -41,10 +39,9 @@ pub struct TestTokenSeedsInit<'info> {
|
|||
pub struct TestInitAssociatedToken<'info> {
|
||||
#[account(
|
||||
init,
|
||||
payer = payer,
|
||||
associated_token::mint = mint,
|
||||
payer = payer,
|
||||
associated_token::authority = payer,
|
||||
|
||||
)]
|
||||
pub token: Account<'info, TokenAccount>,
|
||||
pub mint: Account<'info, Mint>,
|
||||
|
@ -476,3 +473,106 @@ pub struct TestUnsafeFieldSafetyErrors<'info> {
|
|||
pub signer: Signer<'info>,
|
||||
pub system_program: Program<'info, System>,
|
||||
}
|
||||
|
||||
#[derive(Accounts)]
|
||||
pub struct TestConstraintToken<'info> {
|
||||
#[account(
|
||||
token::mint = mint,
|
||||
token::authority = payer
|
||||
)]
|
||||
pub token: Account<'info, TokenAccount>,
|
||||
pub mint: Account<'info, Mint>,
|
||||
pub payer: Signer<'info>,
|
||||
}
|
||||
|
||||
#[derive(Accounts)]
|
||||
pub struct TestAuthorityConstraint<'info> {
|
||||
#[account(
|
||||
token::mint = mint,
|
||||
token::authority = fake_authority
|
||||
)]
|
||||
pub token: Account<'info, TokenAccount>,
|
||||
pub mint: Account<'info, Mint>,
|
||||
pub fake_authority: AccountInfo<'info>,
|
||||
}
|
||||
#[derive(Accounts)]
|
||||
pub struct TestOnlyAuthorityConstraint<'info> {
|
||||
#[account(
|
||||
token::authority = payer
|
||||
)]
|
||||
pub token: Account<'info, TokenAccount>,
|
||||
pub mint: Account<'info, Mint>,
|
||||
pub payer: Signer<'info>,
|
||||
}
|
||||
#[derive(Accounts)]
|
||||
pub struct TestOnlyMintConstraint<'info> {
|
||||
#[account(
|
||||
token::mint = mint,
|
||||
)]
|
||||
pub token: Account<'info, TokenAccount>,
|
||||
pub mint: Account<'info, Mint>,
|
||||
}
|
||||
|
||||
#[derive(Accounts)]
|
||||
#[instruction(decimals: u8)]
|
||||
pub struct TestMintConstraint<'info> {
|
||||
#[account(
|
||||
mint::decimals = decimals,
|
||||
mint::authority = mint_authority,
|
||||
mint::freeze_authority = freeze_authority
|
||||
)]
|
||||
pub mint: Account<'info, Mint>,
|
||||
pub mint_authority: AccountInfo<'info>,
|
||||
pub freeze_authority: AccountInfo<'info>,
|
||||
}
|
||||
|
||||
#[derive(Accounts)]
|
||||
#[instruction(decimals: u8)]
|
||||
pub struct TestMintOnlyDecimalsConstraint<'info> {
|
||||
#[account(
|
||||
mint::decimals = decimals,
|
||||
)]
|
||||
pub mint: Account<'info, Mint>,
|
||||
}
|
||||
|
||||
#[derive(Accounts)]
|
||||
pub struct TestMintAuthorityConstraint<'info> {
|
||||
#[account(
|
||||
mint::authority = mint_authority,
|
||||
mint::freeze_authority = freeze_authority
|
||||
)]
|
||||
pub mint: Account<'info, Mint>,
|
||||
pub mint_authority: AccountInfo<'info>,
|
||||
pub freeze_authority: AccountInfo<'info>,
|
||||
}
|
||||
|
||||
#[derive(Accounts)]
|
||||
pub struct TestMintOneAuthorityConstraint<'info> {
|
||||
#[account(
|
||||
mint::authority = mint_authority,
|
||||
)]
|
||||
pub mint: Account<'info, Mint>,
|
||||
pub mint_authority: AccountInfo<'info>,
|
||||
}
|
||||
|
||||
#[derive(Accounts)]
|
||||
#[instruction(decimals: u8)]
|
||||
pub struct TestMintMissMintAuthConstraint<'info> {
|
||||
#[account(
|
||||
mint::decimals = decimals,
|
||||
mint::freeze_authority = freeze_authority,
|
||||
)]
|
||||
pub mint: Account<'info, Mint>,
|
||||
pub freeze_authority: AccountInfo<'info>,
|
||||
}
|
||||
|
||||
#[derive(Accounts)]
|
||||
pub struct TestAssociatedToken<'info> {
|
||||
#[account(
|
||||
associated_token::mint = mint,
|
||||
associated_token::authority = authority,
|
||||
)]
|
||||
pub token: Account<'info, TokenAccount>,
|
||||
pub mint: Account<'info, Mint>,
|
||||
pub authority: AccountInfo<'info>,
|
||||
}
|
||||
|
|
|
@ -303,4 +303,54 @@ pub mod misc {
|
|||
) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn test_token_constraint(_ctx: Context<TestConstraintToken>) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn test_token_auth_constraint(_ctx: Context<TestAuthorityConstraint>) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn test_only_auth_constraint(_ctx: Context<TestOnlyAuthorityConstraint>) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn test_only_mint_constraint(_ctx: Context<TestOnlyMintConstraint>) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn test_mint_constraint(_ctx: Context<TestMintConstraint>, _decimals: u8) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn test_mint_only_decimals_constraint(
|
||||
_ctx: Context<TestMintOnlyDecimalsConstraint>,
|
||||
_decimals: u8,
|
||||
) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn test_mint_only_auth_constraint(
|
||||
_ctx: Context<TestMintAuthorityConstraint>,
|
||||
) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn test_mint_only_one_auth_constraint(
|
||||
_ctx: Context<TestMintOneAuthorityConstraint>,
|
||||
) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn test_mint_miss_mint_auth_constraint(
|
||||
_ctx: Context<TestMintMissMintAuthConstraint>,
|
||||
_decimals: u8,
|
||||
) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn test_associated_constraint(_ctx: Context<TestAssociatedToken>) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ import {
|
|||
import { Misc } from "../target/types/misc";
|
||||
import { Misc2 } from "../target/types/misc2";
|
||||
const utf8 = anchor.utils.bytes.utf8;
|
||||
const { assert } = require("chai");
|
||||
const { assert, expect } = require("chai");
|
||||
const nativeAssert = require("assert");
|
||||
const miscIdl = require("../target/idl/misc.json");
|
||||
|
||||
|
@ -160,7 +160,7 @@ describe("misc", () => {
|
|||
"Program data: jvbowsvlmkcJAAAA",
|
||||
"Program data: zxM5neEnS1kBAgMEBQYHCAkK",
|
||||
"Program data: g06Ei2GL1gIBAgMEBQYHCAkKCw==",
|
||||
"Program 3TEqcc8xhrhdspwbvoamUJe2borm4Nr72JxL66k6rgrh consumed 5395 of 1400000 compute units",
|
||||
"Program 3TEqcc8xhrhdspwbvoamUJe2borm4Nr72JxL66k6rgrh consumed 3983 of 1400000 compute units",
|
||||
"Program 3TEqcc8xhrhdspwbvoamUJe2borm4Nr72JxL66k6rgrh success",
|
||||
];
|
||||
|
||||
|
@ -232,7 +232,7 @@ describe("misc", () => {
|
|||
solDest: data.publicKey,
|
||||
},
|
||||
});
|
||||
assert.ok(false);
|
||||
expect(false).to.be.true;
|
||||
} catch (err) {
|
||||
const errMsg = "A close constraint was violated";
|
||||
assert.strictEqual(err.error.errorMessage, errMsg);
|
||||
|
@ -266,7 +266,7 @@ describe("misc", () => {
|
|||
).lamports;
|
||||
|
||||
// Retrieved rent exemption sol.
|
||||
assert.ok(afterBalance > beforeBalance);
|
||||
expect(afterBalance > beforeBalance).to.be.true;
|
||||
|
||||
const closedAccount = await program.provider.connection.getAccountInfo(
|
||||
data.publicKey
|
||||
|
@ -989,7 +989,7 @@ describe("misc", () => {
|
|||
owner: anchor.web3.Keypair.generate().publicKey,
|
||||
},
|
||||
});
|
||||
assert.ok(false);
|
||||
expect(false).to.be.true;
|
||||
} catch (_err) {
|
||||
assert.isTrue(_err instanceof AnchorError);
|
||||
const err: AnchorError = _err;
|
||||
|
@ -1028,7 +1028,7 @@ describe("misc", () => {
|
|||
owner: anchor.web3.Keypair.generate().publicKey,
|
||||
},
|
||||
});
|
||||
assert.ok(false);
|
||||
expect(false).to.be.true;
|
||||
} catch (_err) {
|
||||
assert.isTrue(_err instanceof AnchorError);
|
||||
const err: AnchorError = _err;
|
||||
|
@ -1057,7 +1057,7 @@ describe("misc", () => {
|
|||
},
|
||||
signers: [newAcc],
|
||||
});
|
||||
assert.ok(false);
|
||||
expect(false).to.be.true;
|
||||
} catch (_err) {
|
||||
assert.isTrue(_err instanceof AnchorError);
|
||||
const err: AnchorError = _err;
|
||||
|
@ -1091,7 +1091,7 @@ describe("misc", () => {
|
|||
},
|
||||
signers: [mint],
|
||||
});
|
||||
assert.ok(false);
|
||||
expect(false).to.be.true;
|
||||
} catch (_err) {
|
||||
assert.isTrue(_err instanceof AnchorError);
|
||||
const err: AnchorError = _err;
|
||||
|
@ -1125,7 +1125,7 @@ describe("misc", () => {
|
|||
},
|
||||
signers: [mint],
|
||||
});
|
||||
assert.ok(false);
|
||||
expect(false).to.be.true;
|
||||
} catch (_err) {
|
||||
assert.isTrue(_err instanceof AnchorError);
|
||||
const err: AnchorError = _err;
|
||||
|
@ -1159,7 +1159,7 @@ describe("misc", () => {
|
|||
},
|
||||
signers: [mint],
|
||||
});
|
||||
assert.ok(false);
|
||||
expect(false).to.be.true;
|
||||
} catch (_err) {
|
||||
assert.isTrue(_err instanceof AnchorError);
|
||||
const err: AnchorError = _err;
|
||||
|
@ -1206,7 +1206,7 @@ describe("misc", () => {
|
|||
},
|
||||
signers: [token],
|
||||
});
|
||||
assert.ok(false);
|
||||
expect(false).to.be.true;
|
||||
} catch (_err) {
|
||||
assert.isTrue(_err instanceof AnchorError);
|
||||
const err: AnchorError = _err;
|
||||
|
@ -1265,7 +1265,7 @@ describe("misc", () => {
|
|||
},
|
||||
signers: [token],
|
||||
});
|
||||
assert.ok(false);
|
||||
expect(false).to.be.true;
|
||||
} catch (_err) {
|
||||
assert.isTrue(_err instanceof AnchorError);
|
||||
const err: AnchorError = _err;
|
||||
|
@ -1318,7 +1318,7 @@ describe("misc", () => {
|
|||
authority: anchor.web3.Keypair.generate().publicKey,
|
||||
},
|
||||
});
|
||||
assert.ok(false);
|
||||
expect(false).to.be.true;
|
||||
} catch (_err) {
|
||||
assert.isTrue(_err instanceof AnchorError);
|
||||
const err: AnchorError = _err;
|
||||
|
@ -1383,7 +1383,7 @@ describe("misc", () => {
|
|||
authority: program.provider.wallet.publicKey,
|
||||
},
|
||||
});
|
||||
assert.ok(false);
|
||||
expect(false).to.be.true;
|
||||
} catch (_err) {
|
||||
assert.isTrue(_err instanceof AnchorError);
|
||||
const err: AnchorError = _err;
|
||||
|
@ -1449,7 +1449,7 @@ describe("misc", () => {
|
|||
authority: program.provider.wallet.publicKey,
|
||||
},
|
||||
});
|
||||
assert.ok(false);
|
||||
expect(false).to.be.true;
|
||||
} catch (_err) {
|
||||
assert.isTrue(_err instanceof AnchorError);
|
||||
const err: AnchorError = _err;
|
||||
|
@ -1463,7 +1463,6 @@ describe("misc", () => {
|
|||
await program.rpc.testMultidimensionalArray(array2d, {
|
||||
accounts: {
|
||||
data: data.publicKey,
|
||||
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
|
||||
},
|
||||
signers: [data],
|
||||
instructions: [
|
||||
|
@ -1482,7 +1481,6 @@ describe("misc", () => {
|
|||
await program.rpc.testMultidimensionalArrayConstSizes(array2d, {
|
||||
accounts: {
|
||||
data: data.publicKey,
|
||||
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
|
||||
},
|
||||
signers: [data],
|
||||
instructions: [
|
||||
|
@ -1520,7 +1518,7 @@ describe("misc", () => {
|
|||
second: secondPDA,
|
||||
},
|
||||
});
|
||||
assert.ok(false);
|
||||
expect(false).to.be.true;
|
||||
} catch (_err) {
|
||||
assert.isTrue(_err instanceof AnchorError);
|
||||
const err: AnchorError = _err;
|
||||
|
@ -1535,7 +1533,7 @@ describe("misc", () => {
|
|||
second: secondPDA,
|
||||
},
|
||||
});
|
||||
assert.ok(false);
|
||||
expect(false).to.be.true;
|
||||
} catch (_err) {
|
||||
assert.isTrue(_err instanceof AnchorError);
|
||||
const err: AnchorError = _err;
|
||||
|
@ -1574,7 +1572,7 @@ describe("misc", () => {
|
|||
second: secondPDA,
|
||||
},
|
||||
});
|
||||
assert.ok(false);
|
||||
expect(false).to.be.true;
|
||||
} catch (_err) {
|
||||
assert.isTrue(_err instanceof AnchorError);
|
||||
const err: AnchorError = _err;
|
||||
|
@ -1589,7 +1587,7 @@ describe("misc", () => {
|
|||
second: secondPDA,
|
||||
},
|
||||
});
|
||||
assert.ok(false);
|
||||
expect(false).to.be.true;
|
||||
} catch (_err) {
|
||||
assert.isTrue(_err instanceof AnchorError);
|
||||
const err: AnchorError = _err;
|
||||
|
@ -1605,4 +1603,539 @@ describe("misc", () => {
|
|||
});
|
||||
});
|
||||
});
|
||||
describe("Token Constraint Test", () => {
|
||||
it("Token Constraint Test(no init) - Can make token::mint and token::authority", async () => {
|
||||
const mint = anchor.web3.Keypair.generate();
|
||||
await program.rpc.testInitMint({
|
||||
accounts: {
|
||||
mint: mint.publicKey,
|
||||
payer: program.provider.wallet.publicKey,
|
||||
systemProgram: anchor.web3.SystemProgram.programId,
|
||||
tokenProgram: TOKEN_PROGRAM_ID,
|
||||
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
|
||||
},
|
||||
signers: [mint],
|
||||
});
|
||||
|
||||
const token = anchor.web3.Keypair.generate();
|
||||
await program.rpc.testInitToken({
|
||||
accounts: {
|
||||
token: token.publicKey,
|
||||
mint: mint.publicKey,
|
||||
payer: program.provider.wallet.publicKey,
|
||||
systemProgram: anchor.web3.SystemProgram.programId,
|
||||
tokenProgram: TOKEN_PROGRAM_ID,
|
||||
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
|
||||
},
|
||||
signers: [token],
|
||||
});
|
||||
await program.rpc.testTokenConstraint({
|
||||
accounts: {
|
||||
token: token.publicKey,
|
||||
mint: mint.publicKey,
|
||||
payer: program.provider.wallet.publicKey,
|
||||
},
|
||||
});
|
||||
const mintAccount = new Token(
|
||||
program.provider.connection,
|
||||
mint.publicKey,
|
||||
TOKEN_PROGRAM_ID,
|
||||
program.provider.wallet.payer
|
||||
);
|
||||
const account = await mintAccount.getAccountInfo(token.publicKey);
|
||||
assert.isTrue(account.owner.equals(program.provider.wallet.publicKey));
|
||||
assert.isTrue(account.mint.equals(mint.publicKey));
|
||||
});
|
||||
|
||||
it("Token Constraint Test(no init) - Can make only token::authority", async () => {
|
||||
const mint = anchor.web3.Keypair.generate();
|
||||
await program.rpc.testInitMint({
|
||||
accounts: {
|
||||
mint: mint.publicKey,
|
||||
payer: program.provider.wallet.publicKey,
|
||||
systemProgram: anchor.web3.SystemProgram.programId,
|
||||
tokenProgram: TOKEN_PROGRAM_ID,
|
||||
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
|
||||
},
|
||||
signers: [mint],
|
||||
});
|
||||
|
||||
const token = anchor.web3.Keypair.generate();
|
||||
await program.rpc.testInitToken({
|
||||
accounts: {
|
||||
token: token.publicKey,
|
||||
mint: mint.publicKey,
|
||||
payer: program.provider.wallet.publicKey,
|
||||
systemProgram: anchor.web3.SystemProgram.programId,
|
||||
tokenProgram: TOKEN_PROGRAM_ID,
|
||||
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
|
||||
},
|
||||
signers: [token],
|
||||
});
|
||||
await program.rpc.testOnlyAuthConstraint({
|
||||
accounts: {
|
||||
token: token.publicKey,
|
||||
mint: mint.publicKey,
|
||||
payer: program.provider.wallet.publicKey,
|
||||
},
|
||||
});
|
||||
const mintAccount = new Token(
|
||||
program.provider.connection,
|
||||
mint.publicKey,
|
||||
TOKEN_PROGRAM_ID,
|
||||
program.provider.wallet.payer
|
||||
);
|
||||
const account = await mintAccount.getAccountInfo(token.publicKey);
|
||||
assert.isTrue(account.owner.equals(program.provider.wallet.publicKey));
|
||||
});
|
||||
|
||||
it("Token Constraint Test(no init) - Can make only token::mint", async () => {
|
||||
const mint = anchor.web3.Keypair.generate();
|
||||
await program.rpc.testInitMint({
|
||||
accounts: {
|
||||
mint: mint.publicKey,
|
||||
payer: program.provider.wallet.publicKey,
|
||||
systemProgram: anchor.web3.SystemProgram.programId,
|
||||
tokenProgram: TOKEN_PROGRAM_ID,
|
||||
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
|
||||
},
|
||||
signers: [mint],
|
||||
});
|
||||
|
||||
const token = anchor.web3.Keypair.generate();
|
||||
await program.rpc.testInitToken({
|
||||
accounts: {
|
||||
token: token.publicKey,
|
||||
mint: mint.publicKey,
|
||||
payer: program.provider.wallet.publicKey,
|
||||
systemProgram: anchor.web3.SystemProgram.programId,
|
||||
tokenProgram: TOKEN_PROGRAM_ID,
|
||||
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
|
||||
},
|
||||
signers: [token],
|
||||
});
|
||||
await program.rpc.testOnlyMintConstraint({
|
||||
accounts: {
|
||||
token: token.publicKey,
|
||||
mint: mint.publicKey,
|
||||
},
|
||||
});
|
||||
const mintAccount = new Token(
|
||||
program.provider.connection,
|
||||
mint.publicKey,
|
||||
TOKEN_PROGRAM_ID,
|
||||
program.provider.wallet.payer
|
||||
);
|
||||
const account = await mintAccount.getAccountInfo(token.publicKey);
|
||||
assert.isTrue(account.mint.equals(mint.publicKey));
|
||||
});
|
||||
|
||||
it("Token Constraint Test(no init) - throws if token::mint mismatch", async () => {
|
||||
const mint = anchor.web3.Keypair.generate();
|
||||
await program.rpc.testInitMint({
|
||||
accounts: {
|
||||
mint: mint.publicKey,
|
||||
payer: program.provider.wallet.publicKey,
|
||||
systemProgram: anchor.web3.SystemProgram.programId,
|
||||
tokenProgram: TOKEN_PROGRAM_ID,
|
||||
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
|
||||
},
|
||||
signers: [mint],
|
||||
});
|
||||
|
||||
const mint1 = anchor.web3.Keypair.generate();
|
||||
await program.rpc.testInitMint({
|
||||
accounts: {
|
||||
mint: mint1.publicKey,
|
||||
payer: program.provider.wallet.publicKey,
|
||||
systemProgram: anchor.web3.SystemProgram.programId,
|
||||
tokenProgram: TOKEN_PROGRAM_ID,
|
||||
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
|
||||
},
|
||||
signers: [mint1],
|
||||
});
|
||||
|
||||
const token = anchor.web3.Keypair.generate();
|
||||
await program.rpc.testInitToken({
|
||||
accounts: {
|
||||
token: token.publicKey,
|
||||
mint: mint.publicKey,
|
||||
payer: program.provider.wallet.publicKey,
|
||||
systemProgram: anchor.web3.SystemProgram.programId,
|
||||
tokenProgram: TOKEN_PROGRAM_ID,
|
||||
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
|
||||
},
|
||||
signers: [token],
|
||||
});
|
||||
try {
|
||||
await program.rpc.testTokenConstraint({
|
||||
accounts: {
|
||||
token: token.publicKey,
|
||||
mint: mint1.publicKey,
|
||||
payer: program.provider.wallet.publicKey,
|
||||
},
|
||||
});
|
||||
assert.isTrue(false);
|
||||
} catch (_err) {
|
||||
assert.isTrue(_err instanceof AnchorError);
|
||||
const err: AnchorError = _err;
|
||||
assert.strictEqual(err.error.errorCode.number, 2014);
|
||||
assert.strictEqual(err.error.errorCode.code, "ConstraintTokenMint");
|
||||
}
|
||||
});
|
||||
|
||||
it("Token Constraint Test(no init) - throws if token::authority mismatch", async () => {
|
||||
const mint = anchor.web3.Keypair.generate();
|
||||
await program.rpc.testInitMint({
|
||||
accounts: {
|
||||
mint: mint.publicKey,
|
||||
payer: program.provider.wallet.publicKey,
|
||||
systemProgram: anchor.web3.SystemProgram.programId,
|
||||
tokenProgram: TOKEN_PROGRAM_ID,
|
||||
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
|
||||
},
|
||||
signers: [mint],
|
||||
});
|
||||
const token = anchor.web3.Keypair.generate();
|
||||
await program.rpc.testInitToken({
|
||||
accounts: {
|
||||
token: token.publicKey,
|
||||
mint: mint.publicKey,
|
||||
payer: program.provider.wallet.publicKey,
|
||||
systemProgram: anchor.web3.SystemProgram.programId,
|
||||
tokenProgram: TOKEN_PROGRAM_ID,
|
||||
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
|
||||
},
|
||||
signers: [token],
|
||||
});
|
||||
const fakeAuthority = Keypair.generate();
|
||||
try {
|
||||
await program.rpc.testTokenAuthConstraint({
|
||||
accounts: {
|
||||
token: token.publicKey,
|
||||
mint: mint.publicKey,
|
||||
fakeAuthority: fakeAuthority.publicKey,
|
||||
},
|
||||
});
|
||||
assert.isTrue(false);
|
||||
} catch (_err) {
|
||||
assert.isTrue(_err instanceof AnchorError);
|
||||
const err: AnchorError = _err;
|
||||
assert.strictEqual(err.error.errorCode.number, 2015);
|
||||
assert.strictEqual(err.error.errorCode.code, "ConstraintTokenOwner");
|
||||
}
|
||||
});
|
||||
|
||||
it("Token Constraint Test(no init) - throws if both token::authority, token::mint mismatch", async () => {
|
||||
const mint = anchor.web3.Keypair.generate();
|
||||
await program.rpc.testInitMint({
|
||||
accounts: {
|
||||
mint: mint.publicKey,
|
||||
payer: program.provider.wallet.publicKey,
|
||||
systemProgram: anchor.web3.SystemProgram.programId,
|
||||
tokenProgram: TOKEN_PROGRAM_ID,
|
||||
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
|
||||
},
|
||||
signers: [mint],
|
||||
});
|
||||
const mint1 = anchor.web3.Keypair.generate();
|
||||
await program.rpc.testInitMint({
|
||||
accounts: {
|
||||
mint: mint1.publicKey,
|
||||
payer: program.provider.wallet.publicKey,
|
||||
systemProgram: anchor.web3.SystemProgram.programId,
|
||||
tokenProgram: TOKEN_PROGRAM_ID,
|
||||
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
|
||||
},
|
||||
signers: [mint1],
|
||||
});
|
||||
const token = anchor.web3.Keypair.generate();
|
||||
await program.rpc.testInitToken({
|
||||
accounts: {
|
||||
token: token.publicKey,
|
||||
mint: mint.publicKey,
|
||||
payer: program.provider.wallet.publicKey,
|
||||
systemProgram: anchor.web3.SystemProgram.programId,
|
||||
tokenProgram: TOKEN_PROGRAM_ID,
|
||||
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
|
||||
},
|
||||
signers: [token],
|
||||
});
|
||||
const fakeAuthority = Keypair.generate();
|
||||
try {
|
||||
await program.rpc.testTokenAuthConstraint({
|
||||
accounts: {
|
||||
token: token.publicKey,
|
||||
mint: mint1.publicKey,
|
||||
fakeAuthority: fakeAuthority.publicKey,
|
||||
},
|
||||
});
|
||||
assert.isTrue(false);
|
||||
} catch (_err) {
|
||||
assert.isTrue(_err instanceof AnchorError);
|
||||
const err: AnchorError = _err;
|
||||
assert.strictEqual(err.error.errorCode.number, 2015);
|
||||
assert.strictEqual(err.error.errorCode.code, "ConstraintTokenOwner");
|
||||
}
|
||||
});
|
||||
|
||||
it("Mint Constraint Test(no init) - mint::decimals, mint::authority, mint::freeze_authority", async () => {
|
||||
const mint = anchor.web3.Keypair.generate();
|
||||
await program.rpc.testInitMint({
|
||||
accounts: {
|
||||
mint: mint.publicKey,
|
||||
payer: program.provider.wallet.publicKey,
|
||||
systemProgram: anchor.web3.SystemProgram.programId,
|
||||
tokenProgram: TOKEN_PROGRAM_ID,
|
||||
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
|
||||
},
|
||||
signers: [mint],
|
||||
});
|
||||
await program.rpc.testMintConstraint(6, {
|
||||
accounts: {
|
||||
mint: mint.publicKey,
|
||||
mintAuthority: program.provider.wallet.publicKey,
|
||||
freezeAuthority: program.provider.wallet.publicKey,
|
||||
},
|
||||
});
|
||||
const client = new Token(
|
||||
program.provider.connection,
|
||||
mint.publicKey,
|
||||
TOKEN_PROGRAM_ID,
|
||||
program.provider.wallet.payer
|
||||
);
|
||||
const mintAccount = await client.getMintInfo();
|
||||
assert.strictEqual(mintAccount.decimals, 6);
|
||||
assert.isTrue(
|
||||
mintAccount.mintAuthority.equals(program.provider.wallet.publicKey)
|
||||
);
|
||||
assert.isTrue(
|
||||
mintAccount.freezeAuthority.equals(program.provider.wallet.publicKey)
|
||||
);
|
||||
});
|
||||
|
||||
it("Mint Constraint Test(no init) - throws if mint::decimals mismatch", async () => {
|
||||
const mint = anchor.web3.Keypair.generate();
|
||||
await program.rpc.testInitMint({
|
||||
accounts: {
|
||||
mint: mint.publicKey,
|
||||
payer: program.provider.wallet.publicKey,
|
||||
systemProgram: anchor.web3.SystemProgram.programId,
|
||||
tokenProgram: TOKEN_PROGRAM_ID,
|
||||
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
|
||||
},
|
||||
signers: [mint],
|
||||
});
|
||||
const fakeDecimal = 5;
|
||||
try {
|
||||
await program.rpc.testMintConstraint(fakeDecimal, {
|
||||
accounts: {
|
||||
mint: mint.publicKey,
|
||||
mintAuthority: program.provider.wallet.publicKey,
|
||||
freezeAuthority: program.provider.wallet.publicKey,
|
||||
},
|
||||
});
|
||||
assert.isTrue(false);
|
||||
} catch (_err) {
|
||||
assert.isTrue(_err instanceof AnchorError);
|
||||
const err: AnchorError = _err;
|
||||
assert.strictEqual(err.error.errorCode.number, 2018);
|
||||
assert.strictEqual(err.error.errorCode.code, "ConstraintMintDecimals");
|
||||
}
|
||||
});
|
||||
|
||||
it("Mint Constraint Test(no init) - throws if mint::mint_authority mismatch", async () => {
|
||||
const mint = anchor.web3.Keypair.generate();
|
||||
await program.rpc.testInitMint({
|
||||
accounts: {
|
||||
mint: mint.publicKey,
|
||||
payer: program.provider.wallet.publicKey,
|
||||
systemProgram: anchor.web3.SystemProgram.programId,
|
||||
tokenProgram: TOKEN_PROGRAM_ID,
|
||||
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
|
||||
},
|
||||
signers: [mint],
|
||||
});
|
||||
|
||||
const fakeAuthority = Keypair.generate();
|
||||
try {
|
||||
await program.rpc.testMintConstraint(6, {
|
||||
accounts: {
|
||||
mint: mint.publicKey,
|
||||
mintAuthority: fakeAuthority.publicKey,
|
||||
freezeAuthority: program.provider.wallet.publicKey,
|
||||
},
|
||||
});
|
||||
assert.isTrue(false);
|
||||
} catch (_err) {
|
||||
assert.isTrue(_err instanceof AnchorError);
|
||||
const err: AnchorError = _err;
|
||||
assert.strictEqual(err.error.errorCode.number, 2016);
|
||||
assert.strictEqual(
|
||||
err.error.errorCode.code,
|
||||
"ConstraintMintMintAuthority"
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it("Mint Constraint Test(no init) - throws if mint::freeze_authority mismatch", async () => {
|
||||
const mint = anchor.web3.Keypair.generate();
|
||||
await program.rpc.testInitMint({
|
||||
accounts: {
|
||||
mint: mint.publicKey,
|
||||
payer: program.provider.wallet.publicKey,
|
||||
systemProgram: anchor.web3.SystemProgram.programId,
|
||||
tokenProgram: TOKEN_PROGRAM_ID,
|
||||
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
|
||||
},
|
||||
signers: [mint],
|
||||
});
|
||||
|
||||
const fakeAuthority = Keypair.generate();
|
||||
try {
|
||||
await program.rpc.testMintConstraint(6, {
|
||||
accounts: {
|
||||
mint: mint.publicKey,
|
||||
mintAuthority: program.provider.wallet.publicKey,
|
||||
freezeAuthority: fakeAuthority.publicKey,
|
||||
},
|
||||
});
|
||||
assert.isTrue(false);
|
||||
} catch (_err) {
|
||||
assert.isTrue(_err instanceof AnchorError);
|
||||
const err: AnchorError = _err;
|
||||
assert.strictEqual(err.error.errorCode.number, 2017);
|
||||
assert.strictEqual(
|
||||
err.error.errorCode.code,
|
||||
"ConstraintMintFreezeAuthority"
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it("Mint Constraint Test(no init) - can write only mint::decimals", async () => {
|
||||
const mint = anchor.web3.Keypair.generate();
|
||||
await program.rpc.testInitMint({
|
||||
accounts: {
|
||||
mint: mint.publicKey,
|
||||
payer: program.provider.wallet.publicKey,
|
||||
systemProgram: anchor.web3.SystemProgram.programId,
|
||||
tokenProgram: TOKEN_PROGRAM_ID,
|
||||
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
|
||||
},
|
||||
signers: [mint],
|
||||
});
|
||||
|
||||
await program.rpc.testMintOnlyDecimalsConstraint(6, {
|
||||
accounts: {
|
||||
mint: mint.publicKey,
|
||||
},
|
||||
});
|
||||
const client = new Token(
|
||||
program.provider.connection,
|
||||
mint.publicKey,
|
||||
TOKEN_PROGRAM_ID,
|
||||
program.provider.wallet.payer
|
||||
);
|
||||
const mintAccount = await client.getMintInfo();
|
||||
assert.strictEqual(mintAccount.decimals, 6);
|
||||
});
|
||||
|
||||
it("Mint Constraint Test(no init) - can write only mint::authority and mint::freeze_authority", async () => {
|
||||
const mint = anchor.web3.Keypair.generate();
|
||||
await program.rpc.testInitMint({
|
||||
accounts: {
|
||||
mint: mint.publicKey,
|
||||
payer: program.provider.wallet.publicKey,
|
||||
systemProgram: anchor.web3.SystemProgram.programId,
|
||||
tokenProgram: TOKEN_PROGRAM_ID,
|
||||
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
|
||||
},
|
||||
signers: [mint],
|
||||
});
|
||||
|
||||
await program.rpc.testMintOnlyAuthConstraint({
|
||||
accounts: {
|
||||
mint: mint.publicKey,
|
||||
mintAuthority: program.provider.wallet.publicKey,
|
||||
freezeAuthority: program.provider.wallet.publicKey,
|
||||
},
|
||||
});
|
||||
const client = new Token(
|
||||
program.provider.connection,
|
||||
mint.publicKey,
|
||||
TOKEN_PROGRAM_ID,
|
||||
program.provider.wallet.payer
|
||||
);
|
||||
const mintAccount = await client.getMintInfo();
|
||||
assert.isTrue(
|
||||
mintAccount.mintAuthority.equals(program.provider.wallet.publicKey)
|
||||
);
|
||||
assert.isTrue(
|
||||
mintAccount.freezeAuthority.equals(program.provider.wallet.publicKey)
|
||||
);
|
||||
});
|
||||
|
||||
it("Mint Constraint Test(no init) - can write only mint::authority", async () => {
|
||||
const mint = anchor.web3.Keypair.generate();
|
||||
await program.rpc.testInitMint({
|
||||
accounts: {
|
||||
mint: mint.publicKey,
|
||||
payer: program.provider.wallet.publicKey,
|
||||
systemProgram: anchor.web3.SystemProgram.programId,
|
||||
tokenProgram: TOKEN_PROGRAM_ID,
|
||||
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
|
||||
},
|
||||
signers: [mint],
|
||||
});
|
||||
|
||||
await program.rpc.testMintOnlyOneAuthConstraint({
|
||||
accounts: {
|
||||
mint: mint.publicKey,
|
||||
mintAuthority: program.provider.wallet.publicKey,
|
||||
},
|
||||
});
|
||||
const client = new Token(
|
||||
program.provider.connection,
|
||||
mint.publicKey,
|
||||
TOKEN_PROGRAM_ID,
|
||||
program.provider.wallet.payer
|
||||
);
|
||||
const mintAccount = await client.getMintInfo();
|
||||
assert.isTrue(
|
||||
mintAccount.mintAuthority.equals(program.provider.wallet.publicKey)
|
||||
);
|
||||
});
|
||||
|
||||
it("Mint Constraint Test(no init) - can write only mint::decimals and mint::freeze_authority", async () => {
|
||||
const mint = anchor.web3.Keypair.generate();
|
||||
await program.rpc.testInitMint({
|
||||
accounts: {
|
||||
mint: mint.publicKey,
|
||||
payer: program.provider.wallet.publicKey,
|
||||
systemProgram: anchor.web3.SystemProgram.programId,
|
||||
tokenProgram: TOKEN_PROGRAM_ID,
|
||||
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
|
||||
},
|
||||
signers: [mint],
|
||||
});
|
||||
|
||||
await program.rpc.testMintMissMintAuthConstraint(6, {
|
||||
accounts: {
|
||||
mint: mint.publicKey,
|
||||
freezeAuthority: program.provider.wallet.publicKey,
|
||||
},
|
||||
});
|
||||
const client = new Token(
|
||||
program.provider.connection,
|
||||
mint.publicKey,
|
||||
TOKEN_PROGRAM_ID,
|
||||
program.provider.wallet.payer
|
||||
);
|
||||
const mintAccount = await client.getMintInfo();
|
||||
assert.strictEqual(mintAccount.decimals, 6);
|
||||
assert.isTrue(
|
||||
mintAccount.freezeAuthority.equals(program.provider.wallet.publicKey)
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue