Skip to content

Commit

Permalink
Check for close and freeze authorities in token-swap (solana-labs#686)
Browse files Browse the repository at this point in the history
  • Loading branch information
jstarry authored Oct 22, 2020
1 parent ccff57d commit ee99fcf
Show file tree
Hide file tree
Showing 2 changed files with 122 additions and 10 deletions.
6 changes: 6 additions & 0 deletions token-swap/program/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,12 @@ pub enum SwapError {
/// Swap instruction exceeds desired slippage limit
#[error("Swap instruction exceeds desired slippage limit")]
ExceededSlippage,
/// The provided token account has a close authority.
#[error("Token account has a close authority")]
InvalidCloseAuthority,
/// The pool token mint has a freeze authority.
#[error("Pool token mint has a freeze authority")]
InvalidFreezeAuthority,
}
impl From<SwapError> for ProgramError {
fn from(e: SwapError) -> Self {
Expand Down
126 changes: 116 additions & 10 deletions token-swap/program/src/processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ impl Processor {
if COption::Some(*authority_info.key) != pool_mint.mint_authority {
return Err(SwapError::InvalidOwner.into());
}

if token_a.mint == token_b.mint {
return Err(SwapError::RepeatedMint.into());
}
Expand All @@ -188,9 +189,19 @@ impl Processor {
if token_b.delegate.is_some() {
return Err(SwapError::InvalidDelegate.into());
}
if token_a.close_authority.is_some() {
return Err(SwapError::InvalidCloseAuthority.into());
}
if token_b.close_authority.is_some() {
return Err(SwapError::InvalidCloseAuthority.into());
}

if pool_mint.supply != 0 {
return Err(SwapError::InvalidSupply.into());
}
if pool_mint.freeze_authority.is_some() {
return Err(SwapError::InvalidFreezeAuthority.into());
}

let initial_amount = swap_curve.calculator.new_pool_supply();

Expand Down Expand Up @@ -570,6 +581,10 @@ impl PrintProgramError for SwapError {
SwapError::ExceededSlippage => {
info!("Error: Swap instruction exceeds desired slippage limit")
}
SwapError::InvalidCloseAuthority => info!("Error: Token account has a close authority"),
SwapError::InvalidFreezeAuthority => {
info!("Error: Pool token mint has a freeze authority")
}
}
}
}
Expand All @@ -593,7 +608,10 @@ mod tests {
};
use spl_token::{
error::TokenError,
instruction::{approve, initialize_account, initialize_mint, mint_to, revoke},
instruction::{
approve, initialize_account, initialize_mint, mint_to, revoke, set_authority,
AuthorityType,
},
processor::Processor as SplProcessor,
state::{Account as SplAccount, Mint as SplMint},
};
Expand Down Expand Up @@ -635,7 +653,7 @@ mod tests {
Pubkey::find_program_address(&[&swap_key.to_bytes()[..]], &SWAP_PROGRAM_ID);

let (pool_mint_key, mut pool_mint_account) =
create_mint(&TOKEN_PROGRAM_ID, &authority_key);
create_mint(&TOKEN_PROGRAM_ID, &authority_key, None);
let (pool_token_key, pool_token_account) = mint_token(
&TOKEN_PROGRAM_ID,
&pool_mint_key,
Expand All @@ -645,7 +663,7 @@ mod tests {
0,
);
let (token_a_mint_key, mut token_a_mint_account) =
create_mint(&TOKEN_PROGRAM_ID, &user_key);
create_mint(&TOKEN_PROGRAM_ID, &user_key, None);
let (token_a_key, token_a_account) = mint_token(
&TOKEN_PROGRAM_ID,
&token_a_mint_key,
Expand All @@ -655,7 +673,7 @@ mod tests {
token_a_amount,
);
let (token_b_mint_key, mut token_b_mint_account) =
create_mint(&TOKEN_PROGRAM_ID, &user_key);
create_mint(&TOKEN_PROGRAM_ID, &user_key, None);
let (token_b_key, token_b_account) = mint_token(
&TOKEN_PROGRAM_ID,
&token_b_mint_key,
Expand Down Expand Up @@ -1094,7 +1112,11 @@ mod tests {
(account_key, account_account)
}

fn create_mint(program_id: &Pubkey, authority_key: &Pubkey) -> (Pubkey, Account) {
fn create_mint(
program_id: &Pubkey,
authority_key: &Pubkey,
freeze_authority: Option<&Pubkey>,
) -> (Pubkey, Account) {
let mint_key = pubkey_rand();
let mut mint_account = Account::new(
mint_minimum_balance(),
Expand All @@ -1104,7 +1126,7 @@ mod tests {
let mut rent_sysvar_account = rent::create_account(1, &Rent::free());

do_process_instruction(
initialize_mint(&program_id, &mint_key, authority_key, None, 2).unwrap(),
initialize_mint(&program_id, &mint_key, authority_key, freeze_authority, 2).unwrap(),
vec![&mut mint_account, &mut rent_sysvar_account],
)
.unwrap();
Expand Down Expand Up @@ -1263,7 +1285,8 @@ mod tests {

// pool mint authority is not swap authority
{
let (_pool_mint_key, pool_mint_account) = create_mint(&TOKEN_PROGRAM_ID, &user_key);
let (_pool_mint_key, pool_mint_account) =
create_mint(&TOKEN_PROGRAM_ID, &user_key, None);
let old_mint = accounts.pool_mint_account;
accounts.pool_mint_account = pool_mint_account;
assert_eq!(
Expand All @@ -1273,6 +1296,19 @@ mod tests {
accounts.pool_mint_account = old_mint;
}

// pool mint token has freeze authority
{
let (_pool_mint_key, pool_mint_account) =
create_mint(&TOKEN_PROGRAM_ID, &accounts.authority_key, Some(&user_key));
let old_mint = accounts.pool_mint_account;
accounts.pool_mint_account = pool_mint_account;
assert_eq!(
Err(SwapError::InvalidFreezeAuthority.into()),
accounts.initialize_swap()
);
accounts.pool_mint_account = old_mint;
}

// empty token A account
{
let (_token_a_key, token_a_account) = mint_token(
Expand Down Expand Up @@ -1317,7 +1353,7 @@ mod tests {
let old_pool_account = accounts.pool_token_account;

let (_pool_mint_key, pool_mint_account) =
create_mint(&TOKEN_PROGRAM_ID, &accounts.authority_key);
create_mint(&TOKEN_PROGRAM_ID, &accounts.authority_key, None);
accounts.pool_mint_account = pool_mint_account;

let (_empty_pool_token_key, empty_pool_token_account) = mint_token(
Expand Down Expand Up @@ -1430,6 +1466,76 @@ mod tests {
.unwrap();
}

// token A account has close authority
{
do_process_instruction(
set_authority(
&TOKEN_PROGRAM_ID,
&accounts.token_a_key,
Some(&user_key),
AuthorityType::CloseAccount,
&accounts.authority_key,
&[],
)
.unwrap(),
vec![&mut accounts.token_a_account, &mut Account::default()],
)
.unwrap();
assert_eq!(
Err(SwapError::InvalidCloseAuthority.into()),
accounts.initialize_swap()
);

do_process_instruction(
set_authority(
&TOKEN_PROGRAM_ID,
&accounts.token_a_key,
None,
AuthorityType::CloseAccount,
&user_key,
&[],
)
.unwrap(),
vec![&mut accounts.token_a_account, &mut Account::default()],
)
.unwrap();
}

// token B account has close authority
{
do_process_instruction(
set_authority(
&TOKEN_PROGRAM_ID,
&accounts.token_b_key,
Some(&user_key),
AuthorityType::CloseAccount,
&accounts.authority_key,
&[],
)
.unwrap(),
vec![&mut accounts.token_b_account, &mut Account::default()],
)
.unwrap();
assert_eq!(
Err(SwapError::InvalidCloseAuthority.into()),
accounts.initialize_swap()
);

do_process_instruction(
set_authority(
&TOKEN_PROGRAM_ID,
&accounts.token_b_key,
None,
AuthorityType::CloseAccount,
&user_key,
&[],
)
.unwrap(),
vec![&mut accounts.token_b_account, &mut Account::default()],
)
.unwrap();
}

// wrong token program id
{
let wrong_program_id = pubkey_rand();
Expand Down Expand Up @@ -1901,7 +2007,7 @@ mod tests {
mut pool_account,
) = accounts.setup_token_accounts(&user_key, &depositor_key, deposit_a, deposit_b, 0);
let (pool_mint_key, pool_mint_account) =
create_mint(&TOKEN_PROGRAM_ID, &accounts.authority_key);
create_mint(&TOKEN_PROGRAM_ID, &accounts.authority_key, None);
let old_pool_key = accounts.pool_mint_key;
let old_pool_account = accounts.pool_mint_account;
accounts.pool_mint_key = pool_mint_key;
Expand Down Expand Up @@ -2431,7 +2537,7 @@ mod tests {
initial_pool,
);
let (pool_mint_key, pool_mint_account) =
create_mint(&TOKEN_PROGRAM_ID, &accounts.authority_key);
create_mint(&TOKEN_PROGRAM_ID, &accounts.authority_key, None);
let old_pool_key = accounts.pool_mint_key;
let old_pool_account = accounts.pool_mint_account;
accounts.pool_mint_key = pool_mint_key;
Expand Down

0 comments on commit ee99fcf

Please sign in to comment.