Remove supply from Token (#82)

This commit is contained in:
Jack May 2020-07-07 14:34:23 -07:00 committed by GitHub
parent a831eddb8d
commit 56dd582c6f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 121 additions and 341 deletions

View File

@ -73,7 +73,6 @@ typedef enum TokenSwap_SwapInstruction_Tag {
* 0. `[]` Token-swap
* 1. `[]` $authority
* 2. `[writable]` SOURCE Pool account, amount is transferable by $authority.
* 4. `[writable]` Pool MINT account, $authority is the owner.
* 5. `[writable]` token_a Account to withdraw FROM.
* 6. `[writable]` token_b Account to withdraw FROM.
* 7. `[writable]` token_a user Account.

View File

@ -244,7 +244,6 @@ export async function withdraw(): Promise<void> {
await tokenSwap.withdraw(
authority,
tokenAccountPool,
tokenPool.publicKey,
tokenAccountA,
tokenAccountB,
userAccountA,

View File

@ -453,7 +453,6 @@ export class TokenSwap {
async withdraw(
authority: PublicKey,
sourcePoolAccount: PublicKey,
poolToken: PublicKey,
fromA: PublicKey,
fromB: PublicKey,
userAccountA: PublicKey,
@ -468,7 +467,6 @@ export class TokenSwap {
this.withdrawInstruction(
authority,
sourcePoolAccount,
poolToken,
fromA,
fromB,
userAccountA,
@ -483,7 +481,6 @@ export class TokenSwap {
withdrawInstruction(
authority: PublicKey,
sourcePoolAccount: PublicKey,
poolToken: PublicKey,
fromA: PublicKey,
fromB: PublicKey,
userAccountA: PublicKey,
@ -509,7 +506,6 @@ export class TokenSwap {
{pubkey: this.tokenSwap, isSigner: false, isWritable: false},
{pubkey: authority, isSigner: false, isWritable: false},
{pubkey: sourcePoolAccount, isSigner: false, isWritable: true},
{pubkey: poolToken, isSigner: false, isWritable: true},
{pubkey: fromA, isSigner: false, isWritable: true},
{pubkey: fromB, isSigner: false, isWritable: true},
{pubkey: userAccountA, isSigner: false, isWritable: true},

View File

@ -80,7 +80,6 @@ pub enum SwapInstruction {
/// 0. `[]` Token-swap
/// 1. `[]` $authority
/// 2. `[writable]` SOURCE Pool account, amount is transferable by $authority.
/// 4. `[writable]` Pool MINT account, $authority is the owner.
/// 5. `[writable]` token_a Account to withdraw FROM.
/// 6. `[writable]` token_b Account to withdraw FROM.
/// 7. `[writable]` token_a user Account.
@ -289,7 +288,6 @@ pub enum State {
struct Invariant {
token_a: u64,
token_b: u64,
pool: Option<u64>,
fee: Fee,
}
impl Invariant {
@ -310,17 +308,6 @@ impl Invariant {
fn exchange_rate(&self, token_a: u64) -> Option<u64> {
token_a.checked_mul(self.token_b)?.checked_div(self.token_a)
}
fn redeem(&self, user_pool: u64) -> Option<(u64, u64)> {
let token_a = self
.token_a
.checked_mul(user_pool)?
.checked_div(self.pool?)?;
let token_b = self
.token_b
.checked_mul(user_pool)?
.checked_div(self.pool?)?;
Some((token_a, token_b))
}
}
impl State {
@ -403,20 +390,13 @@ impl State {
token_program_id: &Pubkey,
swap: &Pubkey,
burn_account: &Pubkey,
mint: &Pubkey,
authority: &Pubkey,
amount: u64,
) -> Result<(), ProgramError> {
let swap_string = swap.to_string();
let signers = &[&[&swap_string[..32]][..]];
let ix = spl_token::instruction::burn(
token_program_id,
burn_account,
mint,
authority,
&[],
amount,
)?;
let ix =
spl_token::instruction::burn(token_program_id, burn_account, authority, &[], amount)?;
invoke_signed(&ix, accounts, signers)
}
@ -500,9 +480,6 @@ impl State {
if spl_token::option::COption::Some(*authority_info.key) != pool_mint.owner {
return Err(Error::InvalidOwner.into());
}
if 0 != pool_mint.info.supply {
return Err(Error::InvalidSupply.into());
}
if token_b.amount == 0 {
return Err(Error::InvalidSupply.into());
}
@ -573,7 +550,6 @@ impl State {
token_a: into_token.amount,
token_b: from_token.amount,
fee: token_swap.fee,
pool: None,
};
let output = invariant
.swap(amount)
@ -635,7 +611,6 @@ impl State {
token_a: token_a.amount,
token_b: token_b.amount,
fee: token_swap.fee,
pool: None,
};
let b_amount = invariant
.exchange_rate(a_amount)
@ -686,7 +661,6 @@ impl State {
let swap_info = next_account_info(account_info_iter)?;
let authority_info = next_account_info(account_info_iter)?;
let source_info = next_account_info(account_info_iter)?;
let pool_info = next_account_info(account_info_iter)?;
let token_a_info = next_account_info(account_info_iter)?;
let token_b_info = next_account_info(account_info_iter)?;
let dest_token_a_info = next_account_info(account_info_iter)?;
@ -703,23 +677,21 @@ impl State {
if *token_b_info.key != token_swap.token_b {
return Err(Error::InvalidInput.into());
}
if *pool_info.key != token_swap.pool_mint {
return Err(Error::InvalidInput.into());
}
let token_a = Self::token_account_deserialize(token_a_info)?;
let token_b = Self::token_account_deserialize(token_b_info)?;
let pool_token = Self::token_deserialize(pool_info)?;
let invariant = Invariant {
token_a: token_a.amount,
token_b: token_b.amount,
fee: token_swap.fee,
pool: Some(pool_token.info.supply),
};
let (a_amount, b_amount) = invariant
.redeem(amount)
let a_amount = amount;
let b_amount = invariant
.exchange_rate(a_amount)
.ok_or_else(|| Error::CalculationFailure)?;
Self::token_transfer(
accounts,
token_program_info.key,
@ -743,7 +715,6 @@ impl State {
token_program_info.key,
swap_info.key,
source_info.key,
pool_info.key,
authority_info.key,
amount,
)?;
@ -827,7 +798,7 @@ mod tests {
account::Account, account_info::create_is_signer_account_infos, instruction::Instruction,
};
use spl_token::{
instruction::{initialize_account, initialize_mint, TokenInfo},
instruction::{initialize_account, initialize_mint},
state::State as SplState,
};
@ -863,7 +834,7 @@ mod tests {
fn mint_token(
program_id: &Pubkey,
authority_key: &Pubkey,
supply: u64,
amount: u64,
) -> ((Pubkey, Account), (Pubkey, Account)) {
let token_key = pubkey_rand();
let mut token_account = Account::new(0, size_of::<SplState>(), &program_id);
@ -887,13 +858,11 @@ mod tests {
&token_key,
Some(&account_key),
Some(&authority_key),
TokenInfo {
supply,
decimals: 2,
},
amount,
2,
)
.unwrap(),
if supply == 0 {
if amount == 0 {
vec![&mut token_account, &mut authority_account]
} else {
vec![

View File

@ -17,20 +17,6 @@
*/
#define Token_MIN_SIGNERS 1
/**
* Specifies the financial specifics of a token.
*/
typedef struct Token_TokenInfo {
/**
* Total supply of tokens.
*/
uint64_t supply;
/**
* Number of base 10 digits to the right of the decimal place in the total supply.
*/
uint64_t decimals;
} Token_TokenInfo;
/**
* Instructions supported by the token program.
*/
@ -186,9 +172,13 @@ typedef enum Token_TokenInstruction_Tag {
typedef struct Token_InitializeMint_Body {
/**
* The financial specifics of the token.
* Initial amount of tokens to mint.
*/
Token_TokenInfo info;
uint64_t amount;
/**
* Number of base 10 digits to the right of the decimal place.
*/
uint8_t decimals;
} Token_InitializeMint_Body;
typedef struct Token_InitializeMultisig_Body {
@ -271,16 +261,16 @@ typedef struct Token_COption_Pubkey {
* matching types my inter-opt.
*/
typedef struct Token_Token {
/**
* Token details.
*/
Token_TokenInfo info;
/**
* Optional owner, used to mint new tokens. The owner may only
* be provided during mint creation. If no owner is present then the mint
* has a fixed supply and no further tokens may be minted.
*/
Token_COption_Pubkey owner;
/**
* Number of base 10 digits to the right of the decimal place.
*/
uint8_t decimals;
} Token_Token;
/**

View File

@ -120,7 +120,6 @@ export async function createMint(): Promise<void> {
);
const mintInfo = await testToken.getMintInfo();
assert(mintInfo.supply.toNumber() == 10000);
assert(mintInfo.decimals == 2);
assert(mintInfo.owner == null);
@ -264,7 +263,6 @@ export async function mintTo(): Promise<void> {
{
const mintInfo = await testMintableToken.getMintInfo();
assert(mintInfo.supply.toNumber() == 10000);
assert(mintInfo.decimals == 2);
if (mintInfo.owner === null) {
throw new Error('owner should not be null');
@ -285,7 +283,6 @@ export async function mintTo(): Promise<void> {
{
const mintInfo = await testMintableToken.getMintInfo();
assert(mintInfo.supply.toNumber() == 10042);
assert(mintInfo.decimals == 2);
if (mintInfo.owner === null) {
throw new Error('owner should not be null');
@ -303,16 +300,12 @@ export async function mintTo(): Promise<void> {
}
export async function burn(): Promise<void> {
let mintInfo = await testToken.getMintInfo();
const supply = mintInfo.supply.toNumber();
let accountInfo = await testToken.getAccountInfo(testAccount);
const amount = accountInfo.amount.toNumber();
await testToken.burn(testAccount, testAccountOwner, [], 1);
await sleep(500);
mintInfo = await testToken.getMintInfo();
assert(mintInfo.supply.toNumber() == supply - 1);
accountInfo = await testToken.getAccountInfo(testAccount);
assert(accountInfo.amount.toNumber() == amount - 1);
}

View File

@ -57,11 +57,6 @@ export class TokenAmount extends BN {
* Information about the mint
*/
type MintInfo = {|
/**
* Total supply of tokens
*/
supply: TokenAmount,
/**
* Number of base 10 digits to the right of the decimal place
*/
@ -74,11 +69,11 @@ type MintInfo = {|
const MintLayout = BufferLayout.struct([
BufferLayout.u8('state'),
Layout.uint64('supply'),
BufferLayout.nu64('decimals'),
BufferLayout.u32('option'),
Layout.publicKey('owner'),
BufferLayout.nu64('padding'),
BufferLayout.u8('decimals'),
BufferLayout.u16('padding1'),
BufferLayout.nu64('padding2'),
]);
/**
@ -258,10 +253,11 @@ export class Token {
*
* @param connection The connection to use
* @param owner User account that will own the returned account
* @param supply Total supply of the new mint
* @param supply Initial supply to mint
* @param decimals Location of the decimal place
* @param programId Optional token programId, uses the system programId by default
* @return Token object for the newly minted token, Public key of the account holding the total supply of new tokens
* @return Token object for the newly minted token, Public key of the account
* holding the total amount of new tokens
*/
static async createMint(
connection: Connection,
@ -303,7 +299,7 @@ export class Token {
const commandDataLayout = BufferLayout.struct([
BufferLayout.u8('instruction'),
Layout.uint64('supply'),
BufferLayout.nu64('decimals'),
BufferLayout.u8('decimals'),
]);
let data = Buffer.alloc(1024);
{
@ -482,7 +478,6 @@ export class Token {
if (mintInfo.state !== 1) {
throw new Error(`Invalid account data`);
}
mintInfo.supply = TokenAmount.fromBuffer(mintInfo.supply);
if (mintInfo.option === 0) {
mintInfo.owner = null;
} else {
@ -1029,7 +1024,6 @@ export class Token {
let keys = [
{pubkey: account, isSigner: false, isWritable: true},
{pubkey: this.publicKey, isSigner: false, isWritable: true},
];
if (authority instanceof Account) {
keys.push({pubkey: authority.publicKey, isSigner: true, isWritable: false});

View File

@ -13,16 +13,6 @@ pub const MIN_SIGNERS: usize = 1;
/// Maximum number of multisignature signers (max N)
pub const MAX_SIGNERS: usize = 11;
/// Specifies the financial specifics of a token.
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct TokenInfo {
/// Total supply of tokens.
pub supply: u64,
/// Number of base 10 digits to the right of the decimal place in the total supply.
pub decimals: u64,
}
/// Instructions supported by the token program.
#[repr(C)]
#[derive(Clone, Debug, PartialEq)]
@ -43,8 +33,10 @@ pub enum TokenInstruction {
/// present then further minting is supported.
///
InitializeMint {
/// The financial specifics of the token.
info: TokenInfo,
/// Initial amount of tokens to mint.
amount: u64,
/// Number of base 10 digits to the right of the decimal place.
decimals: u8,
},
/// Initializes a new account to hold tokens.
///
@ -188,8 +180,10 @@ impl TokenInstruction {
return Err(ProgramError::InvalidAccountData);
}
#[allow(clippy::cast_ptr_alignment)]
let info = unsafe { *(&input[1] as *const u8 as *const TokenInfo) };
Self::InitializeMint { info }
let amount = unsafe { *(&input[size_of::<u8>()] as *const u8 as *const u64) };
let decimals =
unsafe { *(&input[size_of::<u8>() + size_of::<u64>()] as *const u8) };
Self::InitializeMint { amount, decimals }
}
1 => Self::InitializeAccount,
2 => {
@ -242,11 +236,14 @@ impl TokenInstruction {
pub fn serialize(self: &Self) -> Result<Vec<u8>, ProgramError> {
let mut output = vec![0u8; size_of::<TokenInstruction>()];
match self {
Self::InitializeMint { info } => {
Self::InitializeMint { amount, decimals } => {
output[0] = 0;
#[allow(clippy::cast_ptr_alignment)]
let value = unsafe { &mut *(&mut output[1] as *mut u8 as *mut TokenInfo) };
*value = *info;
let value = unsafe { &mut *(&mut output[size_of::<u8>()] as *mut u8 as *mut u64) };
*value = *amount;
let value =
unsafe { &mut *(&mut output[size_of::<u8>() + size_of::<u64>()] as *mut u8) };
*value = *decimals;
}
Self::InitializeAccount => output[0] = 1,
Self::InitializeMultisig { m } => {
@ -292,12 +289,13 @@ pub fn initialize_mint(
mint_pubkey: &Pubkey,
account_pubkey: Option<&Pubkey>,
owner_pubkey: Option<&Pubkey>,
info: TokenInfo,
amount: u64,
decimals: u8,
) -> Result<Instruction, ProgramError> {
let data = TokenInstruction::InitializeMint { info }.serialize()?;
let data = TokenInstruction::InitializeMint { amount, decimals }.serialize()?;
let mut accounts = vec![AccountMeta::new(*mint_pubkey, false)];
if info.supply != 0 {
if amount != 0 {
match account_pubkey {
Some(pubkey) => accounts.push(AccountMeta::new(*pubkey, false)),
None => {
@ -308,7 +306,7 @@ pub fn initialize_mint(
match owner_pubkey {
Some(pubkey) => accounts.push(AccountMeta::new_readonly(*pubkey, false)),
None => {
if info.supply == 0 {
if amount == 0 {
return Err(TokenError::OwnerRequiredIfNoInitialSupply.into());
}
}
@ -516,7 +514,6 @@ pub fn mint_to(
pub fn burn(
token_program_id: &Pubkey,
account_pubkey: &Pubkey,
mint_pubkey: &Pubkey,
authority_pubkey: &Pubkey,
signer_pubkeys: &[&Pubkey],
amount: u64,
@ -525,7 +522,6 @@ pub fn burn(
let mut accounts = Vec::with_capacity(3 + signer_pubkeys.len());
accounts.push(AccountMeta::new(*account_pubkey, false));
accounts.push(AccountMeta::new(*mint_pubkey, false));
accounts.push(AccountMeta::new_readonly(
*authority_pubkey,
signer_pubkeys.is_empty(),

View File

@ -2,7 +2,7 @@
use crate::{
error::TokenError,
instruction::{is_valid_signer_index, TokenInfo, TokenInstruction, MAX_SIGNERS},
instruction::{is_valid_signer_index, TokenInstruction, MAX_SIGNERS},
option::COption,
};
use solana_sdk::{
@ -17,12 +17,12 @@ use std::mem::size_of;
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct Token {
/// Token details.
pub info: TokenInfo,
/// Optional owner, used to mint new tokens. The owner may only
/// be provided during mint creation. If no owner is present then the mint
/// has a fixed supply and no further tokens may be minted.
pub owner: COption<Pubkey>,
/// Number of base 10 digits to the right of the decimal place.
pub decimals: u8,
}
/// Account that holds tokens or may delegate tokens.
@ -93,7 +93,11 @@ impl Default for State {
}
impl State {
/// Processes an [InitializeMint](enum.TokenInstruction.html) instruction.
pub fn process_initialize_mint(accounts: &[AccountInfo], info: TokenInfo) -> ProgramResult {
pub fn process_initialize_mint(
accounts: &[AccountInfo],
amount: u64,
decimals: u8,
) -> ProgramResult {
let account_info_iter = &mut accounts.iter();
let mint_info = next_account_info(account_info_iter)?;
@ -101,7 +105,7 @@ impl State {
return Err(TokenError::AlreadyInUse.into());
}
let owner = if info.supply != 0 {
let owner = if amount != 0 {
let dest_account_info = next_account_info(account_info_iter)?;
let mut dest_account_data = dest_account_info.data.borrow_mut();
if let State::Account(mut dest_account) = State::deserialize(&dest_account_data)? {
@ -109,7 +113,7 @@ impl State {
return Err(TokenError::MintMismatch.into());
}
dest_account.amount = info.supply;
dest_account.amount = amount;
State::Account(dest_account).serialize(&mut dest_account_data)?;
} else {
return Err(ProgramError::InvalidArgument);
@ -126,7 +130,7 @@ impl State {
return Err(TokenError::OwnerRequiredIfNoInitialSupply.into());
};
State::Mint(Token { info, owner }).serialize(&mut mint_info.data.borrow_mut())
State::Mint(Token { decimals, owner }).serialize(&mut mint_info.data.borrow_mut())
}
/// Processes an [InitializeAccount](enum.TokenInstruction.html) instruction.
@ -335,8 +339,7 @@ impl State {
let dest_account_info = next_account_info(account_info_iter)?;
let owner_info = next_account_info(account_info_iter)?;
let mut mint_data = mint_info.data.borrow_mut();
if let State::Mint(mut token) = State::deserialize(&mint_data)? {
if let State::Mint(token) = State::deserialize(&mint_info.data.borrow())? {
match token.owner {
COption::Some(owner) => {
Self::validate_owner(
@ -357,9 +360,6 @@ impl State {
return Err(TokenError::MintMismatch.into());
}
token.info.supply += amount;
State::Mint(token).serialize(&mut mint_data)?;
dest_account.amount += amount;
State::Account(dest_account).serialize(&mut dest_account_data)
} else {
@ -378,7 +378,6 @@ impl State {
) -> ProgramResult {
let account_info_iter = &mut accounts.iter();
let source_account_info = next_account_info(account_info_iter)?;
let mint_info = next_account_info(account_info_iter)?;
let authority_info = next_account_info(account_info_iter)?;
let (mut source_account, mut source_data) = {
@ -391,19 +390,6 @@ impl State {
}
};
let (mut token, mut mint_data) = {
let mint_data = mint_info.data.borrow_mut();
match State::deserialize(&mint_data)? {
State::Mint(token) => (token, mint_data),
_ => {
return Err(ProgramError::InvalidArgument);
}
}
};
if mint_info.key != &source_account.mint {
return Err(TokenError::MintMismatch.into());
}
if source_account.amount < amount {
return Err(TokenError::InsufficientFunds.into());
}
@ -434,10 +420,8 @@ impl State {
}
source_account.amount -= amount;
token.info.supply -= amount;
State::Account(source_account).serialize(&mut source_data)?;
State::Mint(token).serialize(&mut mint_data)
State::Account(source_account).serialize(&mut source_data)
}
/// Processes an [Instruction](enum.Instruction.html).
@ -445,9 +429,9 @@ impl State {
let instruction = TokenInstruction::deserialize(input)?;
match instruction {
TokenInstruction::InitializeMint { info } => {
TokenInstruction::InitializeMint { amount, decimals } => {
info!("Instruction: InitializeMint");
Self::process_initialize_mint(accounts, info)
Self::process_initialize_mint(accounts, amount, decimals)
}
TokenInstruction::InitializeAccount => {
info!("Instruction: InitializeAccount");
@ -634,17 +618,8 @@ mod tests {
assert_eq!(
Err(ProgramError::InvalidArgument),
do_process_instruction(
initialize_mint(
&program_id,
&mint_key,
Some(&account_key),
None,
TokenInfo {
supply: 1000,
decimals: 2,
}
)
.unwrap(),
initialize_mint(&program_id, &mint_key, Some(&account_key), None, 1000, 2,)
.unwrap(),
vec![&mut mint_account, &mut account_account]
)
);
@ -658,17 +633,7 @@ mod tests {
// create new token
do_process_instruction(
initialize_mint(
&program_id,
&mint_key,
Some(&account_key),
None,
TokenInfo {
supply: 1000,
decimals: 2,
},
)
.unwrap(),
initialize_mint(&program_id, &mint_key, Some(&account_key), None, 1000, 2).unwrap(),
vec![&mut mint_account, &mut account_account],
)
.unwrap();
@ -684,17 +649,8 @@ mod tests {
assert_eq!(
Err(TokenError::MintMismatch.into()),
do_process_instruction(
initialize_mint(
&program_id,
&mint2_key,
Some(&account2_key),
None,
TokenInfo {
supply: 1000,
decimals: 2,
},
)
.unwrap(),
initialize_mint(&program_id, &mint2_key, Some(&account2_key), None, 1000, 2,)
.unwrap(),
vec![&mut mint2_account, &mut account2_account]
)
);
@ -703,17 +659,8 @@ mod tests {
assert_eq!(
Err(TokenError::AlreadyInUse.into()),
do_process_instruction(
initialize_mint(
&program_id,
&mint_key,
Some(&account_key),
None,
TokenInfo {
supply: 1000,
decimals: 2,
},
)
.unwrap(),
initialize_mint(&program_id, &mint_key, Some(&account_key), None, 1000, 2,)
.unwrap(),
vec![&mut mint_account, &mut account_account]
)
);
@ -802,17 +749,7 @@ mod tests {
// create new token
do_process_instruction(
initialize_mint(
&program_id,
&mint_key,
Some(&account_key),
None,
TokenInfo {
supply: 1000,
decimals: 2,
},
)
.unwrap(),
initialize_mint(&program_id, &mint_key, Some(&account_key), None, 1000, 2).unwrap(),
vec![&mut mint_account, &mut account_account],
)
.unwrap();
@ -1102,17 +1039,8 @@ mod tests {
.unwrap();
// create mint-able token without owner
let mut instruction = initialize_mint(
&program_id,
&mint_key,
None,
Some(&owner_key),
TokenInfo {
supply: 0,
decimals: 2,
},
)
.unwrap();
let mut instruction =
initialize_mint(&program_id, &mint_key, None, Some(&owner_key), 0, 2).unwrap();
instruction.accounts.pop();
assert_eq!(
Err(TokenError::OwnerRequiredIfNoInitialSupply.into()),
@ -1120,12 +1048,18 @@ mod tests {
);
// create mint-able token with zero supply
let info = TokenInfo {
supply: 0,
decimals: 2,
};
let amount = 0;
let decimals = 2;
do_process_instruction(
initialize_mint(&program_id, &mint_key, None, Some(&owner_key), info).unwrap(),
initialize_mint(
&program_id,
&mint_key,
None,
Some(&owner_key),
amount,
decimals,
)
.unwrap(),
vec![&mut mint_account, &mut account_account],
)
.unwrap();
@ -1133,7 +1067,7 @@ mod tests {
assert_eq!(
token,
Token {
info,
decimals,
owner: COption::Some(owner_key)
}
);
@ -1148,10 +1082,9 @@ mod tests {
)
.unwrap();
if let State::Mint(token) = State::deserialize(&mint_account.data).unwrap() {
assert_eq!(token.info.supply, 42);
} else {
panic!("not an account");
match State::deserialize(&mint_account.data).unwrap() {
State::Mint(_) => (),
_ => panic!("not a mint"),
}
if let State::Account(dest_account) = State::deserialize(&account_account.data).unwrap() {
assert_eq!(dest_account.amount, 42);
@ -1192,17 +1125,7 @@ mod tests {
// create new token
do_process_instruction(
initialize_mint(
&program_id,
&mint_key,
Some(&account_key),
None,
TokenInfo {
supply: 1000,
decimals: 2,
},
)
.unwrap(),
initialize_mint(&program_id, &mint_key, Some(&account_key), None, 1000, 2).unwrap(),
vec![&mut mint_account, &mut account_account],
)
.unwrap();
@ -1374,10 +1297,8 @@ mod tests {
&mint_key,
Some(&account_key),
Some(&owner_key),
TokenInfo {
supply: 1000,
decimals: 2,
},
1000,
2,
)
.unwrap(),
vec![&mut mint_account, &mut account_account, &mut owner_account],
@ -1414,17 +1335,7 @@ mod tests {
// create new token without owner
do_process_instruction(
initialize_mint(
&program_id,
&mint2_key,
Some(&account2_key),
None,
TokenInfo {
supply: 1000,
decimals: 2,
},
)
.unwrap(),
initialize_mint(&program_id, &mint2_key, Some(&account2_key), None, 1000, 2).unwrap(),
vec![&mut mint2_account, &mut account2_account],
)
.unwrap();
@ -1500,10 +1411,8 @@ mod tests {
&mint_key,
Some(&account_key),
Some(&owner_key),
TokenInfo {
supply: 1000,
decimals: 2,
},
1000,
2,
)
.unwrap(),
vec![&mut mint_account, &mut account_account, &mut owner_account],
@ -1517,10 +1426,9 @@ mod tests {
)
.unwrap();
if let State::Mint(token) = State::deserialize(&mint_account.data).unwrap() {
assert_eq!(token.info.supply, 1000 + 42);
} else {
panic!("not an account");
match State::deserialize(&mint_account.data).unwrap() {
State::Mint(_) => (),
_ => panic!("not a mint"),
}
if let State::Account(dest_account) = State::deserialize(&account2_account.data).unwrap() {
assert_eq!(dest_account.amount, 42);
@ -1640,43 +1548,19 @@ mod tests {
// create new token
do_process_instruction(
initialize_mint(
&program_id,
&mint_key,
Some(&account_key),
None,
TokenInfo {
supply: 1000,
decimals: 2,
},
)
.unwrap(),
initialize_mint(&program_id, &mint_key, Some(&account_key), None, 1000, 2).unwrap(),
vec![&mut mint_account, &mut account_account],
)
.unwrap();
// missing signer
let mut instruction =
burn(&program_id, &account_key, &mint_key, &delegate_key, &[], 42).unwrap();
instruction.accounts[2].is_signer = false;
let mut instruction = burn(&program_id, &account_key, &delegate_key, &[], 42).unwrap();
instruction.accounts[1].is_signer = false;
assert_eq!(
Err(TokenError::OwnerMismatch.into()),
do_process_instruction(
instruction,
vec![
&mut account_account,
&mut mint_account,
&mut delegate_account
],
)
);
// mismatch token
assert_eq!(
Err(TokenError::MintMismatch.into()),
do_process_instruction(
burn(&program_id, &mismatch_key, &mint_key, &owner_key, &[], 42).unwrap(),
vec![&mut mismatch_account, &mut mint_account, &mut owner_account,],
vec![&mut account_account, &mut delegate_account],
)
);
@ -1684,22 +1568,21 @@ mod tests {
assert_eq!(
Err(TokenError::OwnerMismatch.into()),
do_process_instruction(
burn(&program_id, &account_key, &mint_key, &owner2_key, &[], 42).unwrap(),
vec![&mut account_account, &mut mint_account, &mut owner2_account],
burn(&program_id, &account_key, &owner2_key, &[], 42).unwrap(),
vec![&mut account_account, &mut owner2_account],
)
);
// burn
do_process_instruction(
burn(&program_id, &account_key, &mint_key, &owner_key, &[], 42).unwrap(),
vec![&mut account_account, &mut mint_account, &mut owner_account],
burn(&program_id, &account_key, &owner_key, &[], 42).unwrap(),
vec![&mut account_account, &mut owner_account],
)
.unwrap();
if let State::Mint(token) = State::deserialize(&mint_account.data).unwrap() {
assert_eq!(token.info.supply, 1000 - 42);
} else {
panic!("not a token account");
match State::deserialize(&mint_account.data).unwrap() {
State::Mint(_) => (),
_ => panic!("not a mint"),
}
if let State::Account(account) = State::deserialize(&account_account.data).unwrap() {
assert_eq!(account.amount, 1000 - 42);
@ -1711,16 +1594,8 @@ mod tests {
assert_eq!(
Err(TokenError::InsufficientFunds.into()),
do_process_instruction(
burn(
&program_id,
&account_key,
&mint_key,
&owner_key,
&[],
100_000_000
)
.unwrap(),
vec![&mut account_account, &mut mint_account, &mut owner_account],
burn(&program_id, &account_key, &owner_key, &[], 100_000_000).unwrap(),
vec![&mut account_account, &mut owner_account],
)
);
@ -1747,34 +1622,21 @@ mod tests {
assert_eq!(
Err(TokenError::InsufficientFunds.into()),
do_process_instruction(
burn(
&program_id,
&account_key,
&mint_key,
&owner_key,
&[],
100_000_000
)
.unwrap(),
vec![&mut account_account, &mut mint_account, &mut owner_account],
burn(&program_id, &account_key, &owner_key, &[], 100_000_000).unwrap(),
vec![&mut account_account, &mut owner_account],
)
);
// burn via delegate
do_process_instruction(
burn(&program_id, &account_key, &mint_key, &delegate_key, &[], 84).unwrap(),
vec![
&mut account_account,
&mut mint_account,
&mut delegate_account,
],
burn(&program_id, &account_key, &delegate_key, &[], 84).unwrap(),
vec![&mut account_account, &mut delegate_account],
)
.unwrap();
if let State::Mint(token) = State::deserialize(&mint_account.data).unwrap() {
assert_eq!(token.info.supply, 1000 - 42 - 84);
} else {
panic!("not a token account");
match State::deserialize(&mint_account.data).unwrap() {
State::Mint(_) => (),
_ => panic!("not a mint"),
}
if let State::Account(account) = State::deserialize(&account_account.data).unwrap() {
assert_eq!(account.amount, 1000 - 42 - 84);
@ -1786,20 +1648,8 @@ mod tests {
assert_eq!(
Err(TokenError::OwnerMismatch.into()),
do_process_instruction(
burn(
&program_id,
&account_key,
&mint_key,
&delegate_key,
&[],
100
)
.unwrap(),
vec![
&mut account_account,
&mut mint_account,
&mut delegate_account,
],
burn(&program_id, &account_key, &delegate_key, &[], 100).unwrap(),
vec![&mut account_account, &mut delegate_account,],
)
);
}
@ -1892,10 +1742,8 @@ mod tests {
&mint_key,
Some(&account_key),
Some(&multisig_key),
TokenInfo {
supply: 1000,
decimals: 2,
},
1000,
2,
)
.unwrap(),
vec![&mut mint_account, &mut account, &mut multisig_account],
@ -2002,7 +1850,6 @@ mod tests {
burn(
&program_id,
&account_key,
&mint_key,
&multisig_key,
&[&signer_keys[0]],
42,
@ -2010,7 +1857,6 @@ mod tests {
.unwrap(),
vec![
&mut account,
&mut mint_account,
&mut multisig_account,
&mut account_info_iter.next().unwrap(),
],
@ -2023,7 +1869,6 @@ mod tests {
burn(
&program_id,
&account_key,
&mint_key,
&multisig_delegate_key,
&signer_key_refs,
42,
@ -2031,7 +1876,6 @@ mod tests {
.unwrap(),
vec![
&mut account,
&mut mint_account,
&mut multisig_delegate_account,
&mut account_info_iter.next().unwrap(),
&mut account_info_iter.next().unwrap(),