Browse Source

Remove token 1.0

Michael Vines 5 years ago
parent
commit
5d78fccf57

+ 0 - 34
program/Cargo.toml

@@ -1,34 +0,0 @@
-
-# Note: This crate must be built using do.sh
-
-[package]
-name = "spl-token"
-version = "1.0.8"
-description = "Solana Program Library Token"
-authors = ["Solana Maintainers <maintainers@solana.foundation>"]
-repository = "https://github.com/solana-labs/solana-program-library"
-license = "Apache-2.0"
-edition = "2018"
-exclude = ["js/**"]
-
-[features]
-no-entrypoint = []
-skip-no-mangle = ["solana-sdk/skip-no-mangle"]
-program = ["solana-sdk/program"]
-default = ["solana-sdk/default"]
-
-[dependencies]
-num-derive = "0.3"
-num-traits = "0.2"
-remove_dir_all = "=0.5.0"
-solana-sdk = { version = "1.3.4", default-features = false, optional = true }
-thiserror = "1.0"
-
-[dev-dependencies]
-rand = { version = "0.7.0"}
-
-[build-dependencies]
-cbindgen = "=0.14.2"
-
-[lib]
-crate-type = ["cdylib", "lib"]

+ 0 - 2
program/Xargo.toml

@@ -1,2 +0,0 @@
-[target.bpfel-unknown-unknown.dependencies.std]
-features = []

+ 0 - 65
program/build.rs

@@ -1,65 +0,0 @@
-extern crate cbindgen;
-
-use std::env;
-
-fn main() {
-    println!("cargo:rerun-if-env-changed=SPL_CBINDGEN");
-    println!("cargo:rerun-if-changed=inc/token.h");
-    if std::path::Path::new("inc/token.h").exists() && env::var("SPL_CBINDGEN").is_err() {
-        return;
-    }
-
-    println!("cargo:warning=Generating inc/token.h");
-    let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
-    let config = cbindgen::Config {
-        header: Some("/* Autogenerated SPL Token program C Bindings */".to_string()),
-        after_includes: Some(format!(
-            "{}{}{}",
-            format!(
-                "\n#define TOKEN_MAJOR_VERSION {}",
-                env!("CARGO_PKG_VERSION_MAJOR")
-            ),
-            format!(
-                "\n#define TOKEN_MINOR_VERSION {}",
-                env!("CARGO_PKG_VERSION_MINOR")
-            ),
-            format!(
-                "\n#define TOKEN_PATCH_VERSION {}",
-                env!("CARGO_PKG_VERSION_PATCH")
-            )
-        )),
-        language: cbindgen::Language::C,
-        line_length: 80,
-        style: cbindgen::Style::Both,
-        tab_width: 4,
-        cpp_compat: true,
-        pragma_once: true,
-        enumeration: cbindgen::EnumConfig {
-            prefix_with_name: true,
-            ..cbindgen::EnumConfig::default()
-        },
-        export: cbindgen::ExportConfig {
-            prefix: Some("Token_".to_string()),
-            include: vec![
-                "TokenInstruction".to_string(),
-                "Mint".to_string(),
-                "Account".to_string(),
-                "Multisig".to_string(),
-            ],
-            exclude: vec!["DECIMALS".to_string()],
-            ..cbindgen::ExportConfig::default()
-        },
-        parse: cbindgen::ParseConfig {
-            parse_deps: true,
-            include: Some(vec!["solana-sdk".to_string()]),
-            ..cbindgen::ParseConfig::default()
-        },
-        ..cbindgen::Config::default()
-    };
-    cbindgen::Builder::new()
-        .with_crate(crate_dir)
-        .with_config(config)
-        .generate()
-        .unwrap()
-        .write_to_file("inc/token.h");
-}

+ 0 - 359
program/inc/token.h

@@ -1,359 +0,0 @@
-/* Autogenerated SPL Token program C Bindings */
-
-#pragma once
-
-#include <stdarg.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdlib.h>
-
-#define TOKEN_MAJOR_VERSION 1
-#define TOKEN_MINOR_VERSION 0
-#define TOKEN_PATCH_VERSION 8
-
-/**
- * Maximum number of multisignature signers (max N)
- */
-#define Token_MAX_SIGNERS 11
-
-/**
- * Minimum number of multisignature signers (min N)
- */
-#define Token_MIN_SIGNERS 1
-
-/**
- * Instructions supported by the token program.
- */
-typedef enum Token_TokenInstruction_Tag {
-    /**
-     * Initializes a new mint and optionally deposits all the newly minted tokens in an account.
-     *
-     * The `InitializeMint` instruction requires no signers and MUST be included within
-     * the same Transaction as the system program's `CreateInstruction` that creates the account
-     * being initialized.  Otherwise another party can acquire ownership of the uninitialized account.
-     *
-     * Accounts expected by this instruction:
-     *
-     *   0. `[writable]` The mint to initialize.
-     *   1.
-     *      * If supply is non-zero: `[writable]` The account to hold all the newly minted tokens.
-     *      * If supply is zero: `[]` The owner/multisignature of the mint.
-     *   2. `[]` (optional) The owner/multisignature of the mint if supply is non-zero, if
-     *                      present then further minting is supported.
-     *
-     */
-    Token_TokenInstruction_InitializeMint,
-    /**
-     * Initializes a new account to hold tokens.  If this account is associated with the native mint
-     * then the token balance of the initialized account will be equal to the amount of SOL in the account.
-     *
-     * The `InitializeAccount` instruction requires no signers and MUST be included within
-     * the same Transaction as the system program's `CreateInstruction` that creates the account
-     * being initialized.  Otherwise another party can acquire ownership of the uninitialized account.
-     *
-     * Accounts expected by this instruction:
-     *
-     *   0. `[writable]`  The account to initialize.
-     *   1. `[]` The mint this account will be associated with.
-     *   2. `[]` The new account's owner/multisignature.
-     */
-    Token_TokenInstruction_InitializeAccount,
-    /**
-     * Initializes a multisignature account with N provided signers.
-     *
-     * Multisignature accounts can used in place of any single owner/delegate accounts in any
-     * token instruction that require an owner/delegate to be present.  The variant field represents the
-     * number of signers (M) required to validate this multisignature account.
-     *
-     * The `InitializeMultisig` instruction requires no signers and MUST be included within
-     * the same Transaction as the system program's `CreateInstruction` that creates the account
-     * being initialized.  Otherwise another party can acquire ownership of the uninitialized account.
-     *
-     * Accounts expected by this instruction:
-     *
-     *   0. `[writable]` The multisignature account to initialize.
-     *   1. ..1+N. `[]` The signer accounts, must equal to N where 1 <= N <= 11.
-     */
-    Token_TokenInstruction_InitializeMultisig,
-    /**
-     * Transfers tokens from one account to another either directly or via a delegate.  If this
-     * account is associated with the native mint then equal amounts of SOL and Tokens will be
-     * transferred to the destination account.
-     *
-     * Accounts expected by this instruction:
-     *
-     *   * Single owner/delegate
-     *   0. `[writable]` The source account.
-     *   1. `[writable]` The destination account.
-     *   2. '[signer]' The source account's owner/delegate.
-     *
-     *   * Multisignature owner/delegate
-     *   0. `[writable]` The source account.
-     *   1. `[writable]` The destination account.
-     *   2. '[]' The source account's multisignature owner/delegate.
-     *   3. ..3+M '[signer]' M signer accounts.
-     */
-    Token_TokenInstruction_Transfer,
-    /**
-     * Approves a delegate.  A delegate is given the authority over
-     * tokens on behalf of the source account's owner.
-     * Accounts expected by this instruction:
-     *
-     *   * Single owner
-     *   0. `[writable]` The source account.
-     *   1. `[]` The delegate.
-     *   2. `[signer]` The source account owner.
-     *
-     *   * Multisignature owner
-     *   0. `[writable]` The source account.
-     *   1. `[]` The delegate.
-     *   2. '[]' The source account's multisignature owner.
-     *   3. ..3+M '[signer]' M signer accounts
-     */
-    Token_TokenInstruction_Approve,
-    /**
-     * Revokes the delegate's authority.
-     *
-     * Accounts expected by this instruction:
-     *
-     *   * Single owner
-     *   0. `[writable]` The source account.
-     *   1. `[signer]` The source account owner.
-     *
-     *   * Multisignature owner
-     *   0. `[writable]` The source account.
-     *   1. '[]' The source account's multisignature owner.
-     *   2. ..2+M '[signer]' M signer accounts
-     */
-    Token_TokenInstruction_Revoke,
-    /**
-     * Sets a new owner of a mint or account.
-     *
-     * Accounts expected by this instruction:
-     *
-     *   * Single owner
-     *   0. `[writable]` The mint or account to change the owner of.
-     *   1. `[]` The new owner/delegate/multisignature.
-     *   2. `[signer]` The owner of the mint or account.
-     *
-     *   * Multisignature owner
-     *   0. `[writable]` The mint or account to change the owner of.
-     *   1. `[]` The new owner/delegate/multisignature.
-     *   2. `[]` The mint's or account's multisignature owner.
-     *   3. ..3+M '[signer]' M signer accounts
-     */
-    Token_TokenInstruction_SetOwner,
-    /**
-     * Mints new tokens to an account.  The native mint does not support minting.
-     *
-     * Accounts expected by this instruction:
-     *
-     *   * Single owner
-     *   0. `[writable]` The mint.
-     *   1. `[writable]` The account to mint tokens to.
-     *   2. `[signer]` The mint's owner.
-     *
-     *   * Multisignature owner
-     *   0. `[writable]` The mint.
-     *   1. `[writable]` The account to mint tokens to.
-     *   2. `[]` The mint's multisignature owner.
-     *   3. ..3+M '[signer]' M signer accounts.
-     */
-    Token_TokenInstruction_MintTo,
-    /**
-     * Burns tokens by removing them from an account.  `Burn` does not support accounts
-     * associated with the native mint, use `CloseAccount` instead.
-     *
-     * Accounts expected by this instruction:
-     *
-     *   * Single owner/delegate
-     *   0. `[writable]` The account to burn from.
-     *   1. `[signer]` The account's owner/delegate.
-     *
-     *   * Multisignature owner/delegate
-     *   0. `[writable]` The account to burn from.
-     *   1. `[]` The account's multisignature owner/delegate.
-     *   2. ..2+M '[signer]' M signer accounts.
-     */
-    Token_TokenInstruction_Burn,
-    /**
-     * Close an account by transferring all its SOL to the destination account.
-     * Non-native accounts may only be closed if its token amount is zero.
-     *
-     * Accounts expected by this instruction:
-     *
-     *   * Single owner
-     *   0. `[writable]` The account to close.
-     *   1. '[writable]' The destination account.
-     *   2. `[signer]` The account's owner.
-     *
-     *   * Multisignature owner
-     *   0. `[writable]` The account to close.
-     *   1. '[writable]' The destination account.
-     *   2. `[]` The account's multisignature owner.
-     *   3. ..3+M '[signer]' M signer accounts.
-     */
-    Token_TokenInstruction_CloseAccount,
-} Token_TokenInstruction_Tag;
-
-typedef struct Token_TokenInstruction_Token_InitializeMint_Body {
-    /**
-     * Initial amount of tokens to mint.
-     */
-    uint64_t amount;
-    /**
-     * Number of base 10 digits to the right of the decimal place.
-     */
-    uint8_t decimals;
-} Token_TokenInstruction_Token_InitializeMint_Body;
-
-typedef struct Token_TokenInstruction_Token_InitializeMultisig_Body {
-    /**
-     * The number of signers (M) required to validate this multisignature account.
-     */
-    uint8_t m;
-} Token_TokenInstruction_Token_InitializeMultisig_Body;
-
-typedef struct Token_TokenInstruction_Token_Transfer_Body {
-    /**
-     * The amount of tokens to transfer.
-     */
-    uint64_t amount;
-} Token_TokenInstruction_Token_Transfer_Body;
-
-typedef struct Token_TokenInstruction_Token_Approve_Body {
-    /**
-     * The amount of tokens the delegate is approved for.
-     */
-    uint64_t amount;
-} Token_TokenInstruction_Token_Approve_Body;
-
-typedef struct Token_TokenInstruction_Token_MintTo_Body {
-    /**
-     * The amount of new tokens to mint.
-     */
-    uint64_t amount;
-} Token_TokenInstruction_Token_MintTo_Body;
-
-typedef struct Token_TokenInstruction_Token_Burn_Body {
-    /**
-     * The amount of tokens to burn.
-     */
-    uint64_t amount;
-} Token_TokenInstruction_Token_Burn_Body;
-
-typedef struct Token_TokenInstruction {
-    Token_TokenInstruction_Tag tag;
-    union {
-        Token_TokenInstruction_Token_InitializeMint_Body initialize_mint;
-        Token_TokenInstruction_Token_InitializeMultisig_Body initialize_multisig;
-        Token_TokenInstruction_Token_Transfer_Body transfer;
-        Token_TokenInstruction_Token_Approve_Body approve;
-        Token_TokenInstruction_Token_MintTo_Body mint_to;
-        Token_TokenInstruction_Token_Burn_Body burn;
-    };
-} Token_TokenInstruction;
-
-typedef uint8_t Token_Pubkey[32];
-
-/**
- * A C representation of Rust's `std::option::Option`
- */
-typedef enum Token_COption_Pubkey_Tag {
-    /**
-     * No value
-     */
-    Token_COption_Pubkey_None_Pubkey,
-    /**
-     * Some value `T`
-     */
-    Token_COption_Pubkey_Some_Pubkey,
-} Token_COption_Pubkey_Tag;
-
-typedef struct Token_COption_Pubkey_Token_Some_Body_Pubkey {
-    Token_Pubkey _0;
-} Token_COption_Pubkey_Token_Some_Body_Pubkey;
-
-typedef struct Token_COption_Pubkey {
-    Token_COption_Pubkey_Tag tag;
-    union {
-        Token_COption_Pubkey_Token_Some_Body_Pubkey some;
-    };
-} Token_COption_Pubkey;
-
-/**
- * Mint data.
- */
-typedef struct Token_Mint {
-    /**
-     * 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;
-    /**
-     * Is `true` if this structure has been initialized
-     */
-    bool is_initialized;
-} Token_Mint;
-
-/**
- * Account data.
- */
-typedef struct Token_Account {
-    /**
-     * The mint associated with this account
-     */
-    Token_Pubkey mint;
-    /**
-     * The owner of this account.
-     */
-    Token_Pubkey owner;
-    /**
-     * The amount of tokens this account holds.
-     */
-    uint64_t amount;
-    /**
-     * If `delegate` is `Some` then `delegated_amount` represents
-     * the amount authorized by the delegate
-     */
-    Token_COption_Pubkey delegate;
-    /**
-     * Is `true` if this structure has been initialized
-     */
-    bool is_initialized;
-    /**
-     * Is this a native token
-     */
-    bool is_native;
-    /**
-     * The amount delegated
-     */
-    uint64_t delegated_amount;
-} Token_Account;
-
-/**
- * Multisignature data.
- */
-typedef struct Token_Multisig {
-    /**
-     * Number of signers required
-     */
-    uint8_t m;
-    /**
-     * Number of valid signers
-     */
-    uint8_t n;
-    /**
-     * Is `true` if this structure has been initialized
-     */
-    bool is_initialized;
-    /**
-     * Signer public keys
-     */
-    Token_Pubkey signers[Token_MAX_SIGNERS];
-} Token_Multisig;

+ 0 - 1
program/program-id.md

@@ -1 +0,0 @@
-TokenSVp5gheXUvJ6jGWGeCsgPKgnE3YgdGKRVCMY9o

+ 0 - 24
program/src/entrypoint.rs

@@ -1,24 +0,0 @@
-//! Program entrypoint
-
-#![cfg(feature = "program")]
-#![cfg(not(feature = "no-entrypoint"))]
-
-use crate::{error::TokenError, processor::Processor};
-use solana_sdk::{
-    account_info::AccountInfo, entrypoint, entrypoint::ProgramResult,
-    program_error::PrintProgramError, pubkey::Pubkey,
-};
-
-entrypoint!(process_instruction);
-fn process_instruction<'a>(
-    program_id: &Pubkey,
-    accounts: &'a [AccountInfo<'a>],
-    instruction_data: &[u8],
-) -> ProgramResult {
-    if let Err(error) = Processor::process(program_id, accounts, instruction_data) {
-        // catch the error so we can print it
-        error.print::<TokenError>();
-        return Err(error);
-    }
-    Ok(())
-}

+ 0 - 59
program/src/error.rs

@@ -1,59 +0,0 @@
-//! Error types
-
-use num_derive::FromPrimitive;
-use solana_sdk::{decode_error::DecodeError, program_error::ProgramError};
-use thiserror::Error;
-
-/// Errors that may be returned by the Token program.
-#[derive(Clone, Debug, Eq, Error, FromPrimitive, PartialEq)]
-pub enum TokenError {
-    /// Insufficient funds for the operation requested.
-    #[error("Insufficient funds")]
-    InsufficientFunds,
-    /// Account not associated with this Mint.
-    #[error("Account not associated with this Mint")]
-    MintMismatch,
-    /// Owner does not match.
-    #[error("Owner does not match")]
-    OwnerMismatch,
-    /// This token's supply is fixed and new tokens cannot be minted.
-    #[error("Fixed supply")]
-    FixedSupply,
-    /// The account cannot be initialized because it is already being used.
-    #[error("AlreadyInUse")]
-    AlreadyInUse,
-    /// An owner is required if initial supply is zero.
-    #[error("An owner is required if supply is zero")]
-    OwnerRequiredIfNoInitialSupply,
-    /// Invalid number of provided signers.
-    #[error("Invalid number of provided signers")]
-    InvalidNumberOfProvidedSigners,
-    /// Invalid number of required signers.
-    #[error("Invalid number of required signers")]
-    InvalidNumberOfRequiredSigners,
-    /// State is uninitialized.
-    #[error("State is unititialized")]
-    UninitializedState,
-    /// Instruction does not support native tokens
-    #[error("Instruction does not support native tokens")]
-    NativeNotSupported,
-    /// Instruction does not support non-native tokens
-    #[error("Instruction does not support non-native tokens")]
-    NonNativeNotSupported,
-    /// Invalid instruction
-    #[error("Invalid instruction")]
-    InvalidInstruction,
-    /// Operation overflowed
-    #[error("Operation overflowed")]
-    Overflow,
-}
-impl From<TokenError> for ProgramError {
-    fn from(e: TokenError) -> Self {
-        ProgramError::Custom(e as u32)
-    }
-}
-impl<T> DecodeError<T> for TokenError {
-    fn type_of() -> &'static str {
-        "TokenError"
-    }
-}

+ 0 - 708
program/src/instruction.rs

@@ -1,708 +0,0 @@
-//! Instruction types
-
-use crate::error::TokenError;
-use solana_sdk::{
-    instruction::{AccountMeta, Instruction},
-    program_error::ProgramError,
-    pubkey::Pubkey,
-};
-use std::mem::size_of;
-
-/// Minimum number of multisignature signers (min N)
-pub const MIN_SIGNERS: usize = 1;
-/// Maximum number of multisignature signers (max N)
-pub const MAX_SIGNERS: usize = 11;
-
-/// Instructions supported by the token program.
-#[repr(C)]
-#[derive(Clone, Debug, PartialEq)]
-pub enum TokenInstruction {
-    /// Initializes a new mint and optionally deposits all the newly minted tokens in an account.
-    ///
-    /// The `InitializeMint` instruction requires no signers and MUST be included within
-    /// the same Transaction as the system program's `CreateInstruction` that creates the account
-    /// being initialized.  Otherwise another party can acquire ownership of the uninitialized account.
-    ///
-    /// Accounts expected by this instruction:
-    ///
-    ///   0. `[writable]` The mint to initialize.
-    ///   1.
-    ///      * If supply is non-zero: `[writable]` The account to hold all the newly minted tokens.
-    ///      * If supply is zero: `[]` The owner/multisignature of the mint.
-    ///   2. `[]` (optional) The owner/multisignature of the mint if supply is non-zero, if
-    ///                      present then further minting is supported.
-    ///
-    InitializeMint {
-        /// 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.  If this account is associated with the native mint
-    /// then the token balance of the initialized account will be equal to the amount of SOL in the account.
-    ///
-    /// The `InitializeAccount` instruction requires no signers and MUST be included within
-    /// the same Transaction as the system program's `CreateInstruction` that creates the account
-    /// being initialized.  Otherwise another party can acquire ownership of the uninitialized account.
-    ///
-    /// Accounts expected by this instruction:
-    ///
-    ///   0. `[writable]`  The account to initialize.
-    ///   1. `[]` The mint this account will be associated with.
-    ///   2. `[]` The new account's owner/multisignature.
-    InitializeAccount,
-    /// Initializes a multisignature account with N provided signers.
-    ///
-    /// Multisignature accounts can used in place of any single owner/delegate accounts in any
-    /// token instruction that require an owner/delegate to be present.  The variant field represents the
-    /// number of signers (M) required to validate this multisignature account.
-    ///
-    /// The `InitializeMultisig` instruction requires no signers and MUST be included within
-    /// the same Transaction as the system program's `CreateInstruction` that creates the account
-    /// being initialized.  Otherwise another party can acquire ownership of the uninitialized account.
-    ///
-    /// Accounts expected by this instruction:
-    ///
-    ///   0. `[writable]` The multisignature account to initialize.
-    ///   1. ..1+N. `[]` The signer accounts, must equal to N where 1 <= N <= 11.
-    InitializeMultisig {
-        /// The number of signers (M) required to validate this multisignature account.
-        m: u8,
-    },
-    /// Transfers tokens from one account to another either directly or via a delegate.  If this
-    /// account is associated with the native mint then equal amounts of SOL and Tokens will be
-    /// transferred to the destination account.
-    ///
-    /// Accounts expected by this instruction:
-    ///
-    ///   * Single owner/delegate
-    ///   0. `[writable]` The source account.
-    ///   1. `[writable]` The destination account.
-    ///   2. '[signer]' The source account's owner/delegate.
-    ///
-    ///   * Multisignature owner/delegate
-    ///   0. `[writable]` The source account.
-    ///   1. `[writable]` The destination account.
-    ///   2. '[]' The source account's multisignature owner/delegate.
-    ///   3. ..3+M '[signer]' M signer accounts.
-    Transfer {
-        /// The amount of tokens to transfer.
-        amount: u64,
-    },
-    /// Approves a delegate.  A delegate is given the authority over
-    /// tokens on behalf of the source account's owner.
-
-    /// Accounts expected by this instruction:
-    ///
-    ///   * Single owner
-    ///   0. `[writable]` The source account.
-    ///   1. `[]` The delegate.
-    ///   2. `[signer]` The source account owner.
-    ///
-    ///   * Multisignature owner
-    ///   0. `[writable]` The source account.
-    ///   1. `[]` The delegate.
-    ///   2. '[]' The source account's multisignature owner.
-    ///   3. ..3+M '[signer]' M signer accounts
-    Approve {
-        /// The amount of tokens the delegate is approved for.
-        amount: u64,
-    },
-    /// Revokes the delegate's authority.
-    ///
-    /// Accounts expected by this instruction:
-    ///
-    ///   * Single owner
-    ///   0. `[writable]` The source account.
-    ///   1. `[signer]` The source account owner.
-    ///
-    ///   * Multisignature owner
-    ///   0. `[writable]` The source account.
-    ///   1. '[]' The source account's multisignature owner.
-    ///   2. ..2+M '[signer]' M signer accounts
-    Revoke,
-    /// Sets a new owner of a mint or account.
-    ///
-    /// Accounts expected by this instruction:
-    ///
-    ///   * Single owner
-    ///   0. `[writable]` The mint or account to change the owner of.
-    ///   1. `[]` The new owner/delegate/multisignature.
-    ///   2. `[signer]` The owner of the mint or account.
-    ///
-    ///   * Multisignature owner
-    ///   0. `[writable]` The mint or account to change the owner of.
-    ///   1. `[]` The new owner/delegate/multisignature.
-    ///   2. `[]` The mint's or account's multisignature owner.
-    ///   3. ..3+M '[signer]' M signer accounts
-    SetOwner,
-    /// Mints new tokens to an account.  The native mint does not support minting.
-    ///
-    /// Accounts expected by this instruction:
-    ///
-    ///   * Single owner
-    ///   0. `[writable]` The mint.
-    ///   1. `[writable]` The account to mint tokens to.
-    ///   2. `[signer]` The mint's owner.
-    ///
-    ///   * Multisignature owner
-    ///   0. `[writable]` The mint.
-    ///   1. `[writable]` The account to mint tokens to.
-    ///   2. `[]` The mint's multisignature owner.
-    ///   3. ..3+M '[signer]' M signer accounts.
-    MintTo {
-        /// The amount of new tokens to mint.
-        amount: u64,
-    },
-    /// Burns tokens by removing them from an account.  `Burn` does not support accounts
-    /// associated with the native mint, use `CloseAccount` instead.
-    ///
-    /// Accounts expected by this instruction:
-    ///
-    ///   * Single owner/delegate
-    ///   0. `[writable]` The account to burn from.
-    ///   1. `[signer]` The account's owner/delegate.
-    ///
-    ///   * Multisignature owner/delegate
-    ///   0. `[writable]` The account to burn from.
-    ///   1. `[]` The account's multisignature owner/delegate.
-    ///   2. ..2+M '[signer]' M signer accounts.
-    Burn {
-        /// The amount of tokens to burn.
-        amount: u64,
-    },
-    /// Close an account by transferring all its SOL to the destination account.
-    /// Non-native accounts may only be closed if its token amount is zero.
-    ///
-    /// Accounts expected by this instruction:
-    ///
-    ///   * Single owner
-    ///   0. `[writable]` The account to close.
-    ///   1. '[writable]' The destination account.
-    ///   2. `[signer]` The account's owner.
-    ///
-    ///   * Multisignature owner
-    ///   0. `[writable]` The account to close.
-    ///   1. '[writable]' The destination account.
-    ///   2. `[]` The account's multisignature owner.
-    ///   3. ..3+M '[signer]' M signer accounts.
-    CloseAccount,
-}
-impl TokenInstruction {
-    /// Unpacks a byte buffer into a [TokenInstruction](enum.TokenInstruction.html).
-    pub fn unpack(input: &[u8]) -> Result<Self, ProgramError> {
-        if input.len() < size_of::<u8>() {
-            return Err(TokenError::InvalidInstruction.into());
-        }
-        Ok(match input[0] {
-            0 => {
-                if input.len() < size_of::<u8>() + size_of::<u64>() + size_of::<u8>() {
-                    return Err(TokenError::InvalidInstruction.into());
-                }
-                #[allow(clippy::cast_ptr_alignment)]
-                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 => {
-                if input.len() < size_of::<u8>() + size_of::<u8>() {
-                    return Err(TokenError::InvalidInstruction.into());
-                }
-                #[allow(clippy::cast_ptr_alignment)]
-                let m = unsafe { *(&input[1] as *const u8) };
-                Self::InitializeMultisig { m }
-            }
-            3 => {
-                if input.len() < size_of::<u8>() + size_of::<u64>() {
-                    return Err(TokenError::InvalidInstruction.into());
-                }
-                #[allow(clippy::cast_ptr_alignment)]
-                let amount = unsafe { *(&input[size_of::<u8>()] as *const u8 as *const u64) };
-                Self::Transfer { amount }
-            }
-            4 => {
-                if input.len() < size_of::<u8>() + size_of::<u64>() {
-                    return Err(TokenError::InvalidInstruction.into());
-                }
-                #[allow(clippy::cast_ptr_alignment)]
-                let amount = unsafe { *(&input[size_of::<u8>()] as *const u8 as *const u64) };
-                Self::Approve { amount }
-            }
-            5 => Self::Revoke,
-            6 => Self::SetOwner,
-            7 => {
-                if input.len() < size_of::<u8>() + size_of::<u64>() {
-                    return Err(TokenError::InvalidInstruction.into());
-                }
-                #[allow(clippy::cast_ptr_alignment)]
-                let amount = unsafe { *(&input[size_of::<u8>()] as *const u8 as *const u64) };
-                Self::MintTo { amount }
-            }
-            8 => {
-                if input.len() < size_of::<u8>() + size_of::<u64>() {
-                    return Err(TokenError::InvalidInstruction.into());
-                }
-                #[allow(clippy::cast_ptr_alignment)]
-                let amount = unsafe { *(&input[size_of::<u8>()] as *const u8 as *const u64) };
-                Self::Burn { amount }
-            }
-            9 => Self::CloseAccount,
-            _ => return Err(TokenError::InvalidInstruction.into()),
-        })
-    }
-
-    /// Packs a [TokenInstruction](enum.TokenInstruction.html) into a byte buffer.
-    pub fn pack(&self) -> Result<Vec<u8>, ProgramError> {
-        let mut output = vec![0u8; size_of::<TokenInstruction>()];
-        let mut output_len = 0;
-        match self {
-            Self::InitializeMint { amount, decimals } => {
-                output[output_len] = 0;
-                output_len += size_of::<u8>();
-
-                #[allow(clippy::cast_ptr_alignment)]
-                let value = unsafe { &mut *(&mut output[output_len] as *mut u8 as *mut u64) };
-                *value = *amount;
-                output_len += size_of::<u64>();
-
-                let value = unsafe { &mut *(&mut output[output_len] as *mut u8) };
-                *value = *decimals;
-                output_len += size_of::<u8>();
-            }
-            Self::InitializeAccount => {
-                output[output_len] = 1;
-                output_len += size_of::<u8>();
-            }
-            Self::InitializeMultisig { m } => {
-                output[output_len] = 2;
-                output_len += size_of::<u8>();
-
-                #[allow(clippy::cast_ptr_alignment)]
-                let value = unsafe { &mut *(&mut output[output_len] as *mut u8 as *mut u8) };
-                *value = *m;
-                output_len += size_of::<u8>();
-            }
-            Self::Transfer { amount } => {
-                output[output_len] = 3;
-                output_len += size_of::<u8>();
-
-                #[allow(clippy::cast_ptr_alignment)]
-                let value = unsafe { &mut *(&mut output[output_len] as *mut u8 as *mut u64) };
-                *value = *amount;
-                output_len += size_of::<u64>();
-            }
-            Self::Approve { amount } => {
-                output[output_len] = 4;
-                output_len += size_of::<u8>();
-
-                #[allow(clippy::cast_ptr_alignment)]
-                let value = unsafe { &mut *(&mut output[output_len] as *mut u8 as *mut u64) };
-                *value = *amount;
-                output_len += size_of::<u64>();
-            }
-            Self::Revoke => {
-                output[output_len] = 5;
-                output_len += size_of::<u8>();
-            }
-            Self::SetOwner => {
-                output[output_len] = 6;
-                output_len += size_of::<u8>();
-            }
-            Self::MintTo { amount } => {
-                output[output_len] = 7;
-                output_len += size_of::<u8>();
-
-                #[allow(clippy::cast_ptr_alignment)]
-                let value = unsafe { &mut *(&mut output[output_len] as *mut u8 as *mut u64) };
-                *value = *amount;
-                output_len += size_of::<u64>();
-            }
-            Self::Burn { amount } => {
-                output[output_len] = 8;
-                output_len += size_of::<u8>();
-
-                #[allow(clippy::cast_ptr_alignment)]
-                let value = unsafe { &mut *(&mut output[output_len] as *mut u8 as *mut u64) };
-                *value = *amount;
-                output_len += size_of::<u64>();
-            }
-            Self::CloseAccount => {
-                output[output_len] = 9;
-                output_len += size_of::<u8>();
-            }
-        }
-
-        output.truncate(output_len);
-        Ok(output)
-    }
-}
-
-/// Creates a 'InitializeMint' instruction.
-pub fn initialize_mint(
-    token_program_id: &Pubkey,
-    mint_pubkey: &Pubkey,
-    account_pubkey: Option<&Pubkey>,
-    owner_pubkey: Option<&Pubkey>,
-    amount: u64,
-    decimals: u8,
-) -> Result<Instruction, ProgramError> {
-    let data = TokenInstruction::InitializeMint { amount, decimals }.pack()?;
-
-    let mut accounts = vec![AccountMeta::new(*mint_pubkey, false)];
-    if amount != 0 {
-        match account_pubkey {
-            Some(pubkey) => accounts.push(AccountMeta::new(*pubkey, false)),
-            None => {
-                return Err(ProgramError::NotEnoughAccountKeys);
-            }
-        }
-    }
-    match owner_pubkey {
-        Some(pubkey) => accounts.push(AccountMeta::new_readonly(*pubkey, false)),
-        None => {
-            if amount == 0 {
-                return Err(TokenError::OwnerRequiredIfNoInitialSupply.into());
-            }
-        }
-    }
-
-    Ok(Instruction {
-        program_id: *token_program_id,
-        accounts,
-        data,
-    })
-}
-
-/// Creates a `InitializeAccount` instruction.
-pub fn initialize_account(
-    token_program_id: &Pubkey,
-    account_pubkey: &Pubkey,
-    mint_pubkey: &Pubkey,
-    owner_pubkey: &Pubkey,
-) -> Result<Instruction, ProgramError> {
-    let data = TokenInstruction::InitializeAccount.pack()?;
-
-    let accounts = vec![
-        AccountMeta::new(*account_pubkey, false),
-        AccountMeta::new_readonly(*mint_pubkey, false),
-        AccountMeta::new_readonly(*owner_pubkey, false),
-    ];
-
-    Ok(Instruction {
-        program_id: *token_program_id,
-        accounts,
-        data,
-    })
-}
-
-/// Creates a `InitializeMultisig` instruction.
-pub fn initialize_multisig(
-    token_program_id: &Pubkey,
-    multisig_pubkey: &Pubkey,
-    signer_pubkeys: &[&Pubkey],
-    m: u8,
-) -> Result<Instruction, ProgramError> {
-    if !is_valid_signer_index(m as usize)
-        || !is_valid_signer_index(signer_pubkeys.len())
-        || m as usize > signer_pubkeys.len()
-    {
-        return Err(ProgramError::MissingRequiredSignature);
-    }
-    let data = TokenInstruction::InitializeMultisig { m }.pack()?;
-
-    let mut accounts = Vec::with_capacity(1 + signer_pubkeys.len());
-    accounts.push(AccountMeta::new(*multisig_pubkey, false));
-    for signer_pubkey in signer_pubkeys.iter() {
-        accounts.push(AccountMeta::new_readonly(**signer_pubkey, false));
-    }
-
-    Ok(Instruction {
-        program_id: *token_program_id,
-        accounts,
-        data,
-    })
-}
-
-/// Creates a `Transfer` instruction.
-pub fn transfer(
-    token_program_id: &Pubkey,
-    source_pubkey: &Pubkey,
-    destination_pubkey: &Pubkey,
-    authority_pubkey: &Pubkey,
-    signer_pubkeys: &[&Pubkey],
-    amount: u64,
-) -> Result<Instruction, ProgramError> {
-    let data = TokenInstruction::Transfer { amount }.pack()?;
-
-    let mut accounts = Vec::with_capacity(3 + signer_pubkeys.len());
-    accounts.push(AccountMeta::new(*source_pubkey, false));
-    accounts.push(AccountMeta::new(*destination_pubkey, false));
-    accounts.push(AccountMeta::new_readonly(
-        *authority_pubkey,
-        signer_pubkeys.is_empty(),
-    ));
-    for signer_pubkey in signer_pubkeys.iter() {
-        accounts.push(AccountMeta::new(**signer_pubkey, true));
-    }
-
-    Ok(Instruction {
-        program_id: *token_program_id,
-        accounts,
-        data,
-    })
-}
-
-/// Creates an `Approve` instruction.
-pub fn approve(
-    token_program_id: &Pubkey,
-    source_pubkey: &Pubkey,
-    delegate_pubkey: &Pubkey,
-    owner_pubkey: &Pubkey,
-    signer_pubkeys: &[&Pubkey],
-    amount: u64,
-) -> Result<Instruction, ProgramError> {
-    let data = TokenInstruction::Approve { amount }.pack()?;
-
-    let mut accounts = Vec::with_capacity(3 + signer_pubkeys.len());
-    accounts.push(AccountMeta::new(*source_pubkey, false));
-    accounts.push(AccountMeta::new_readonly(*delegate_pubkey, false));
-    accounts.push(AccountMeta::new_readonly(
-        *owner_pubkey,
-        signer_pubkeys.is_empty(),
-    ));
-    for signer_pubkey in signer_pubkeys.iter() {
-        accounts.push(AccountMeta::new(**signer_pubkey, true));
-    }
-
-    Ok(Instruction {
-        program_id: *token_program_id,
-        accounts,
-        data,
-    })
-}
-
-/// Creates a `Revoke` instruction.
-pub fn revoke(
-    token_program_id: &Pubkey,
-    source_pubkey: &Pubkey,
-    owner_pubkey: &Pubkey,
-    signer_pubkeys: &[&Pubkey],
-) -> Result<Instruction, ProgramError> {
-    let data = TokenInstruction::Revoke.pack()?;
-
-    let mut accounts = Vec::with_capacity(2 + signer_pubkeys.len());
-    accounts.push(AccountMeta::new_readonly(*source_pubkey, false));
-    accounts.push(AccountMeta::new_readonly(
-        *owner_pubkey,
-        signer_pubkeys.is_empty(),
-    ));
-    for signer_pubkey in signer_pubkeys.iter() {
-        accounts.push(AccountMeta::new(**signer_pubkey, true));
-    }
-
-    Ok(Instruction {
-        program_id: *token_program_id,
-        accounts,
-        data,
-    })
-}
-
-/// Creates a `SetOwner` instruction.
-pub fn set_owner(
-    token_program_id: &Pubkey,
-    owned_pubkey: &Pubkey,
-    new_owner_pubkey: &Pubkey,
-    owner_pubkey: &Pubkey,
-    signer_pubkeys: &[&Pubkey],
-) -> Result<Instruction, ProgramError> {
-    let data = TokenInstruction::SetOwner.pack()?;
-
-    let mut accounts = Vec::with_capacity(3 + signer_pubkeys.len());
-    accounts.push(AccountMeta::new(*owned_pubkey, false));
-    accounts.push(AccountMeta::new_readonly(*new_owner_pubkey, false));
-    accounts.push(AccountMeta::new_readonly(
-        *owner_pubkey,
-        signer_pubkeys.is_empty(),
-    ));
-    for signer_pubkey in signer_pubkeys.iter() {
-        accounts.push(AccountMeta::new(**signer_pubkey, true));
-    }
-
-    Ok(Instruction {
-        program_id: *token_program_id,
-        accounts,
-        data,
-    })
-}
-
-/// Creates a `MintTo` instruction.
-pub fn mint_to(
-    token_program_id: &Pubkey,
-    mint_pubkey: &Pubkey,
-    account_pubkey: &Pubkey,
-    owner_pubkey: &Pubkey,
-    signer_pubkeys: &[&Pubkey],
-    amount: u64,
-) -> Result<Instruction, ProgramError> {
-    let data = TokenInstruction::MintTo { amount }.pack()?;
-
-    let mut accounts = Vec::with_capacity(3 + signer_pubkeys.len());
-    accounts.push(AccountMeta::new(*mint_pubkey, false));
-    accounts.push(AccountMeta::new(*account_pubkey, false));
-    accounts.push(AccountMeta::new_readonly(
-        *owner_pubkey,
-        signer_pubkeys.is_empty(),
-    ));
-    for signer_pubkey in signer_pubkeys.iter() {
-        accounts.push(AccountMeta::new(**signer_pubkey, true));
-    }
-
-    Ok(Instruction {
-        program_id: *token_program_id,
-        accounts,
-        data,
-    })
-}
-
-/// Creates a `Burn` instruction.
-pub fn burn(
-    token_program_id: &Pubkey,
-    account_pubkey: &Pubkey,
-    authority_pubkey: &Pubkey,
-    signer_pubkeys: &[&Pubkey],
-    amount: u64,
-) -> Result<Instruction, ProgramError> {
-    let data = TokenInstruction::Burn { amount }.pack()?;
-
-    let mut accounts = Vec::with_capacity(2 + signer_pubkeys.len());
-    accounts.push(AccountMeta::new(*account_pubkey, false));
-    accounts.push(AccountMeta::new_readonly(
-        *authority_pubkey,
-        signer_pubkeys.is_empty(),
-    ));
-    for signer_pubkey in signer_pubkeys.iter() {
-        accounts.push(AccountMeta::new(**signer_pubkey, true));
-    }
-
-    Ok(Instruction {
-        program_id: *token_program_id,
-        accounts,
-        data,
-    })
-}
-
-/// Creates a `CloseAccount` instruction.
-pub fn close_account(
-    token_program_id: &Pubkey,
-    account_pubkey: &Pubkey,
-    destination_pubkey: &Pubkey,
-    owner_pubkey: &Pubkey,
-    signer_pubkeys: &[&Pubkey],
-) -> Result<Instruction, ProgramError> {
-    let data = TokenInstruction::CloseAccount.pack()?;
-
-    let mut accounts = Vec::with_capacity(3 + signer_pubkeys.len());
-    accounts.push(AccountMeta::new(*account_pubkey, false));
-    accounts.push(AccountMeta::new(*destination_pubkey, false));
-    accounts.push(AccountMeta::new_readonly(
-        *owner_pubkey,
-        signer_pubkeys.is_empty(),
-    ));
-    for signer_pubkey in signer_pubkeys.iter() {
-        accounts.push(AccountMeta::new(**signer_pubkey, true));
-    }
-
-    Ok(Instruction {
-        program_id: *token_program_id,
-        accounts,
-        data,
-    })
-}
-
-/// Utility function that checks index is between MIN_SIGNERS and MAX_SIGNERS
-pub fn is_valid_signer_index(index: usize) -> bool {
-    !(index < MIN_SIGNERS || index > MAX_SIGNERS)
-}
-
-#[cfg(test)]
-mod test {
-    use super::*;
-
-    #[test]
-    fn test_instruction_packing() {
-        let check = TokenInstruction::InitializeMint {
-            amount: 1,
-            decimals: 2,
-        };
-        let packed = check.pack().unwrap();
-        let expect = Vec::from([0u8, 1, 0, 0, 0, 0, 0, 0, 0, 2]);
-        assert_eq!(packed, expect);
-        let unpacked = TokenInstruction::unpack(&expect).unwrap();
-        assert_eq!(unpacked, check);
-
-        let check = TokenInstruction::InitializeAccount;
-        let packed = check.pack().unwrap();
-        let expect = Vec::from([1u8]);
-        assert_eq!(packed, expect);
-        let unpacked = TokenInstruction::unpack(&expect).unwrap();
-        assert_eq!(unpacked, check);
-
-        let check = TokenInstruction::InitializeMultisig { m: 1 };
-        let packed = check.pack().unwrap();
-        let expect = Vec::from([2u8, 1]);
-        assert_eq!(packed, expect);
-        let unpacked = TokenInstruction::unpack(&expect).unwrap();
-        assert_eq!(unpacked, check);
-
-        let check = TokenInstruction::Transfer { amount: 1 };
-        let packed = check.pack().unwrap();
-        let expect = Vec::from([3u8, 1, 0, 0, 0, 0, 0, 0, 0]);
-        assert_eq!(packed, expect);
-        let unpacked = TokenInstruction::unpack(&expect).unwrap();
-        assert_eq!(unpacked, check);
-
-        let check = TokenInstruction::Approve { amount: 1 };
-        let packed = check.pack().unwrap();
-        let expect = Vec::from([4u8, 1, 0, 0, 0, 0, 0, 0, 0]);
-        assert_eq!(packed, expect);
-        let unpacked = TokenInstruction::unpack(&expect).unwrap();
-        assert_eq!(unpacked, check);
-
-        let check = TokenInstruction::Revoke;
-        let packed = check.pack().unwrap();
-        let expect = Vec::from([5u8]);
-        assert_eq!(packed, expect);
-        let unpacked = TokenInstruction::unpack(&expect).unwrap();
-        assert_eq!(unpacked, check);
-
-        let check = TokenInstruction::SetOwner;
-        let packed = check.pack().unwrap();
-        let expect = Vec::from([6u8]);
-        assert_eq!(packed, expect);
-        let unpacked = TokenInstruction::unpack(&expect).unwrap();
-        assert_eq!(unpacked, check);
-
-        let check = TokenInstruction::MintTo { amount: 1 };
-        let packed = check.pack().unwrap();
-        let expect = Vec::from([7u8, 1, 0, 0, 0, 0, 0, 0, 0]);
-        assert_eq!(packed, expect);
-        let unpacked = TokenInstruction::unpack(&expect).unwrap();
-        assert_eq!(unpacked, check);
-
-        let check = TokenInstruction::Burn { amount: 1 };
-        let packed = check.pack().unwrap();
-        let expect = Vec::from([8u8, 1, 0, 0, 0, 0, 0, 0, 0]);
-        assert_eq!(packed, expect);
-        let unpacked = TokenInstruction::unpack(&expect).unwrap();
-        assert_eq!(unpacked, check);
-
-        let check = TokenInstruction::CloseAccount;
-        let packed = check.pack().unwrap();
-        let expect = Vec::from([9u8]);
-        assert_eq!(packed, expect);
-        let unpacked = TokenInstruction::unpack(&expect).unwrap();
-        assert_eq!(unpacked, check);
-    }
-}

+ 0 - 28
program/src/lib.rs

@@ -1,28 +0,0 @@
-#![deny(missing_docs)]
-
-//! An ERC20-like Token program for the Solana blockchain
-
-pub mod entrypoint;
-pub mod error;
-pub mod instruction;
-pub mod native_mint;
-pub mod option;
-pub mod processor;
-pub mod state;
-
-// Export current solana-sdk types for downstream users who may also be building with a different
-// solana-sdk version
-pub use solana_sdk;
-
-/// Convert the UI representation of a token amount (using the decimals field defined in its mint)
-/// to the raw amount
-pub fn ui_amount_to_amount(ui_amount: f64, decimals: u8) -> u64 {
-    (ui_amount * 10_usize.pow(decimals as u32) as f64) as u64
-}
-
-/// Convert a raw amount to its UI representation (using the decimals field defined in its mint)
-pub fn amount_to_ui_amount(amount: u64, decimals: u8) -> f64 {
-    amount as f64 / 10_usize.pow(decimals as u32) as f64
-}
-
-solana_sdk::declare_id!("TokenSVp5gheXUvJ6jGWGeCsgPKgnE3YgdGKRVCMY9o");

+ 0 - 24
program/src/native_mint.rs

@@ -1,24 +0,0 @@
-//! The Mint that represents the native token
-
-/// There are 10^9 lamports in one SOL
-pub const DECIMALS: u8 = 9;
-
-// The Mint for native SOL Token accounts
-solana_sdk::declare_id!("So11111111111111111111111111111111111111111");
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-    use solana_sdk::native_token::*;
-
-    #[test]
-    fn test_decimals() {
-        assert!(
-            lamports_to_sol(42) - crate::amount_to_ui_amount(42, DECIMALS).abs() < f64::EPSILON
-        );
-        assert_eq!(
-            sol_to_lamports(42.),
-            crate::ui_amount_to_amount(42., DECIMALS)
-        );
-    }
-}

+ 0 - 965
program/src/option.rs

@@ -1,965 +0,0 @@
-//! A C representation of Rust's `std::option::Option` used accross the FFI
-//! boundary for Solana program interfaces
-//!
-//! This implementation mostly matches `std::option` except iterators since the iteration
-//! trait requires returning `std::option::Option`
-
-use std::pin::Pin;
-use std::{
-    convert, hint, mem,
-    ops::{Deref, DerefMut},
-};
-
-/// A C representation of Rust's `std::option::Option`
-#[repr(C)]
-#[derive(Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
-pub enum COption<T> {
-    /// No value
-    None,
-    /// Some value `T`
-    Some(T),
-}
-
-/////////////////////////////////////////////////////////////////////////////
-// Type implementation
-/////////////////////////////////////////////////////////////////////////////
-
-impl<T> COption<T> {
-    /////////////////////////////////////////////////////////////////////////
-    // Querying the contained values
-    /////////////////////////////////////////////////////////////////////////
-
-    /// Returns `true` if the option is a [`COption::Some`] value.
-    ///
-    /// # Examples
-    ///
-    /// ```ignore
-    /// let x: COption<u32> = COption::Some(2);
-    /// assert_eq!(x.is_some(), true);
-    ///
-    /// let x: COption<u32> = COption::None;
-    /// assert_eq!(x.is_some(), false);
-    /// ```
-    ///
-    /// [`COption::Some`]: #variant.COption::Some
-    #[must_use = "if you intended to assert that this has a value, consider `.unwrap()` instead"]
-    #[inline]
-    pub fn is_some(&self) -> bool {
-        match *self {
-            COption::Some(_) => true,
-            COption::None => false,
-        }
-    }
-
-    /// Returns `true` if the option is a [`COption::None`] value.
-    ///
-    /// # Examples
-    ///
-    /// ```ignore
-    /// let x: COption<u32> = COption::Some(2);
-    /// assert_eq!(x.is_none(), false);
-    ///
-    /// let x: COption<u32> = COption::None;
-    /// assert_eq!(x.is_none(), true);
-    /// ```
-    ///
-    /// [`COption::None`]: #variant.COption::None
-    #[must_use = "if you intended to assert that this doesn't have a value, consider \
-                  `.and_then(|| panic!(\"`COption` had a value when expected `COption::None`\"))` instead"]
-    #[inline]
-    pub fn is_none(&self) -> bool {
-        !self.is_some()
-    }
-
-    /// Returns `true` if the option is a [`COption::Some`] value containing the given value.
-    ///
-    /// # Examples
-    ///
-    /// ```ignore
-    /// #![feature(option_result_contains)]
-    ///
-    /// let x: COption<u32> = COption::Some(2);
-    /// assert_eq!(x.contains(&2), true);
-    ///
-    /// let x: COption<u32> = COption::Some(3);
-    /// assert_eq!(x.contains(&2), false);
-    ///
-    /// let x: COption<u32> = COption::None;
-    /// assert_eq!(x.contains(&2), false);
-    /// ```
-    #[must_use]
-    #[inline]
-    pub fn contains<U>(&self, x: &U) -> bool
-    where
-        U: PartialEq<T>,
-    {
-        match self {
-            COption::Some(y) => x == y,
-            COption::None => false,
-        }
-    }
-
-    /////////////////////////////////////////////////////////////////////////
-    // Adapter for working with references
-    /////////////////////////////////////////////////////////////////////////
-
-    /// Converts from `&COption<T>` to `COption<&T>`.
-    ///
-    /// # Examples
-    ///
-    /// Converts an `COption<`[`String`]`>` into an `COption<`[`usize`]`>`, preserving the original.
-    /// The [`map`] method takes the `self` argument by value, consuming the original,
-    /// so this technique uses `as_ref` to first take an `COption` to a reference
-    /// to the value inside the original.
-    ///
-    /// [`map`]: enum.COption.html#method.map
-    /// [`String`]: ../../std/string/struct.String.html
-    /// [`usize`]: ../../std/primitive.usize.html
-    ///
-    /// ```ignore
-    /// let text: COption<String> = COption::Some("Hello, world!".to_string());
-    /// // First, cast `COption<String>` to `COption<&String>` with `as_ref`,
-    /// // then consume *that* with `map`, leaving `text` on the stack.
-    /// let text_length: COption<usize> = text.as_ref().map(|s| s.len());
-    /// println!("still can print text: {:?}", text);
-    /// ```
-    #[inline]
-    pub fn as_ref(&self) -> COption<&T> {
-        match *self {
-            COption::Some(ref x) => COption::Some(x),
-            COption::None => COption::None,
-        }
-    }
-
-    /// Converts from `&mut COption<T>` to `COption<&mut T>`.
-    ///
-    /// # Examples
-    ///
-    /// ```ignore
-    /// let mut x = COption::Some(2);
-    /// match x.as_mut() {
-    ///     COption::Some(v) => *v = 42,
-    ///     COption::None => {},
-    /// }
-    /// assert_eq!(x, COption::Some(42));
-    /// ```
-    #[inline]
-    pub fn as_mut(&mut self) -> COption<&mut T> {
-        match *self {
-            COption::Some(ref mut x) => COption::Some(x),
-            COption::None => COption::None,
-        }
-    }
-
-    /// Converts from [`Pin`]`<&COption<T>>` to `COption<`[`Pin`]`<&T>>`.
-    ///
-    /// [`Pin`]: ../pin/struct.Pin.html
-    #[inline]
-    #[allow(clippy::wrong_self_convention)]
-    pub fn as_pin_ref(self: Pin<&Self>) -> COption<Pin<&T>> {
-        unsafe { Pin::get_ref(self).as_ref().map(|x| Pin::new_unchecked(x)) }
-    }
-
-    /// Converts from [`Pin`]`<&mut COption<T>>` to `COption<`[`Pin`]`<&mut T>>`.
-    ///
-    /// [`Pin`]: ../pin/struct.Pin.html
-    #[inline]
-    #[allow(clippy::wrong_self_convention)]
-    pub fn as_pin_mut(self: Pin<&mut Self>) -> COption<Pin<&mut T>> {
-        unsafe {
-            Pin::get_unchecked_mut(self)
-                .as_mut()
-                .map(|x| Pin::new_unchecked(x))
-        }
-    }
-
-    /////////////////////////////////////////////////////////////////////////
-    // Getting to contained values
-    /////////////////////////////////////////////////////////////////////////
-
-    /// Unwraps an option, yielding the content of a [`COption::Some`].
-    ///
-    /// # Panics
-    ///
-    /// Panics if the value is a [`COption::None`] with a custom panic message provided by
-    /// `msg`.
-    ///
-    /// [`COption::Some`]: #variant.COption::Some
-    /// [`COption::None`]: #variant.COption::None
-    ///
-    /// # Examples
-    ///
-    /// ```ignore
-    /// let x = COption::Some("value");
-    /// assert_eq!(x.expect("the world is ending"), "value");
-    /// ```
-    ///
-    /// ```ignore{.should_panic}
-    /// let x: COption<&str> = COption::None;
-    /// x.expect("the world is ending"); // panics with `the world is ending`
-    /// ```
-    #[inline]
-    pub fn expect(self, msg: &str) -> T {
-        match self {
-            COption::Some(val) => val,
-            COption::None => expect_failed(msg),
-        }
-    }
-
-    /// Moves the value `v` out of the `COption<T>` if it is [`COption::Some(v)`].
-    ///
-    /// In general, because this function may panic, its use is discouraged.
-    /// Instead, prefer to use pattern matching and handle the [`COption::None`]
-    /// case explicitly.
-    ///
-    /// # Panics
-    ///
-    /// Panics if the self value equals [`COption::None`].
-    ///
-    /// [`COption::Some(v)`]: #variant.COption::Some
-    /// [`COption::None`]: #variant.COption::None
-    ///
-    /// # Examples
-    ///
-    /// ```ignore
-    /// let x = COption::Some("air");
-    /// assert_eq!(x.unwrap(), "air");
-    /// ```
-    ///
-    /// ```ignore{.should_panic}
-    /// let x: COption<&str> = COption::None;
-    /// assert_eq!(x.unwrap(), "air"); // fails
-    /// ```
-    #[inline]
-    pub fn unwrap(self) -> T {
-        match self {
-            COption::Some(val) => val,
-            COption::None => panic!("called `COption::unwrap()` on a `COption::None` value"),
-        }
-    }
-
-    /// Returns the contained value or a default.
-    ///
-    /// Arguments passed to `unwrap_or` are eagerly evaluated; if you are passing
-    /// the result of a function call, it is recommended to use [`unwrap_or_else`],
-    /// which is lazily evaluated.
-    ///
-    /// [`unwrap_or_else`]: #method.unwrap_or_else
-    ///
-    /// # Examples
-    ///
-    /// ```ignore
-    /// assert_eq!(COption::Some("car").unwrap_or("bike"), "car");
-    /// assert_eq!(COption::None.unwrap_or("bike"), "bike");
-    /// ```
-    #[inline]
-    pub fn unwrap_or(self, def: T) -> T {
-        match self {
-            COption::Some(x) => x,
-            COption::None => def,
-        }
-    }
-
-    /// Returns the contained value or computes it from a closure.
-    ///
-    /// # Examples
-    ///
-    /// ```ignore
-    /// let k = 10;
-    /// assert_eq!(COption::Some(4).unwrap_or_else(|| 2 * k), 4);
-    /// assert_eq!(COption::None.unwrap_or_else(|| 2 * k), 20);
-    /// ```
-    #[inline]
-    pub fn unwrap_or_else<F: FnOnce() -> T>(self, f: F) -> T {
-        match self {
-            COption::Some(x) => x,
-            COption::None => f(),
-        }
-    }
-
-    /////////////////////////////////////////////////////////////////////////
-    // Transforming contained values
-    /////////////////////////////////////////////////////////////////////////
-
-    /// Maps an `COption<T>` to `COption<U>` by applying a function to a contained value.
-    ///
-    /// # Examples
-    ///
-    /// Converts an `COption<`[`String`]`>` into an `COption<`[`usize`]`>`, consuming the original:
-    ///
-    /// [`String`]: ../../std/string/struct.String.html
-    /// [`usize`]: ../../std/primitive.usize.html
-    ///
-    /// ```ignore
-    /// let maybe_some_string = COption::Some(String::from("Hello, World!"));
-    /// // `COption::map` takes self *by value*, consuming `maybe_some_string`
-    /// let maybe_some_len = maybe_some_string.map(|s| s.len());
-    ///
-    /// assert_eq!(maybe_some_len, COption::Some(13));
-    /// ```
-    #[inline]
-    pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> COption<U> {
-        match self {
-            COption::Some(x) => COption::Some(f(x)),
-            COption::None => COption::None,
-        }
-    }
-
-    /// Applies a function to the contained value (if any),
-    /// or returns the provided default (if not).
-    ///
-    /// # Examples
-    ///
-    /// ```ignore
-    /// let x = COption::Some("foo");
-    /// assert_eq!(x.map_or(42, |v| v.len()), 3);
-    ///
-    /// let x: COption<&str> = COption::None;
-    /// assert_eq!(x.map_or(42, |v| v.len()), 42);
-    /// ```
-    #[inline]
-    pub fn map_or<U, F: FnOnce(T) -> U>(self, default: U, f: F) -> U {
-        match self {
-            COption::Some(t) => f(t),
-            COption::None => default,
-        }
-    }
-
-    /// Applies a function to the contained value (if any),
-    /// or computes a default (if not).
-    ///
-    /// # Examples
-    ///
-    /// ```ignore
-    /// let k = 21;
-    ///
-    /// let x = COption::Some("foo");
-    /// assert_eq!(x.map_or_else(|| 2 * k, |v| v.len()), 3);
-    ///
-    /// let x: COption<&str> = COption::None;
-    /// assert_eq!(x.map_or_else(|| 2 * k, |v| v.len()), 42);
-    /// ```
-    #[inline]
-    pub fn map_or_else<U, D: FnOnce() -> U, F: FnOnce(T) -> U>(self, default: D, f: F) -> U {
-        match self {
-            COption::Some(t) => f(t),
-            COption::None => default(),
-        }
-    }
-
-    /// Transforms the `COption<T>` into a [`Result<T, E>`], mapping [`COption::Some(v)`] to
-    /// [`Ok(v)`] and [`COption::None`] to [`Err(err)`].
-    ///
-    /// Arguments passed to `ok_or` are eagerly evaluated; if you are passing the
-    /// result of a function call, it is recommended to use [`ok_or_else`], which is
-    /// lazily evaluated.
-    ///
-    /// [`Result<T, E>`]: ../../std/result/enum.Result.html
-    /// [`Ok(v)`]: ../../std/result/enum.Result.html#variant.Ok
-    /// [`Err(err)`]: ../../std/result/enum.Result.html#variant.Err
-    /// [`COption::None`]: #variant.COption::None
-    /// [`COption::Some(v)`]: #variant.COption::Some
-    /// [`ok_or_else`]: #method.ok_or_else
-    ///
-    /// # Examples
-    ///
-    /// ```ignore
-    /// let x = COption::Some("foo");
-    /// assert_eq!(x.ok_or(0), Ok("foo"));
-    ///
-    /// let x: COption<&str> = COption::None;
-    /// assert_eq!(x.ok_or(0), Err(0));
-    /// ```
-    #[inline]
-    pub fn ok_or<E>(self, err: E) -> Result<T, E> {
-        match self {
-            COption::Some(v) => Ok(v),
-            COption::None => Err(err),
-        }
-    }
-
-    /// Transforms the `COption<T>` into a [`Result<T, E>`], mapping [`COption::Some(v)`] to
-    /// [`Ok(v)`] and [`COption::None`] to [`Err(err())`].
-    ///
-    /// [`Result<T, E>`]: ../../std/result/enum.Result.html
-    /// [`Ok(v)`]: ../../std/result/enum.Result.html#variant.Ok
-    /// [`Err(err())`]: ../../std/result/enum.Result.html#variant.Err
-    /// [`COption::None`]: #variant.COption::None
-    /// [`COption::Some(v)`]: #variant.COption::Some
-    ///
-    /// # Examples
-    ///
-    /// ```ignore
-    /// let x = COption::Some("foo");
-    /// assert_eq!(x.ok_or_else(|| 0), Ok("foo"));
-    ///
-    /// let x: COption<&str> = COption::None;
-    /// assert_eq!(x.ok_or_else(|| 0), Err(0));
-    /// ```
-    #[inline]
-    pub fn ok_or_else<E, F: FnOnce() -> E>(self, err: F) -> Result<T, E> {
-        match self {
-            COption::Some(v) => Ok(v),
-            COption::None => Err(err()),
-        }
-    }
-
-    /////////////////////////////////////////////////////////////////////////
-    // Boolean operations on the values, eager and lazy
-    /////////////////////////////////////////////////////////////////////////
-
-    /// Returns [`COption::None`] if the option is [`COption::None`], otherwise returns `optb`.
-    ///
-    /// [`COption::None`]: #variant.COption::None
-    ///
-    /// # Examples
-    ///
-    /// ```ignore
-    /// let x = COption::Some(2);
-    /// let y: COption<&str> = COption::None;
-    /// assert_eq!(x.and(y), COption::None);
-    ///
-    /// let x: COption<u32> = COption::None;
-    /// let y = COption::Some("foo");
-    /// assert_eq!(x.and(y), COption::None);
-    ///
-    /// let x = COption::Some(2);
-    /// let y = COption::Some("foo");
-    /// assert_eq!(x.and(y), COption::Some("foo"));
-    ///
-    /// let x: COption<u32> = COption::None;
-    /// let y: COption<&str> = COption::None;
-    /// assert_eq!(x.and(y), COption::None);
-    /// ```
-    #[inline]
-    pub fn and<U>(self, optb: COption<U>) -> COption<U> {
-        match self {
-            COption::Some(_) => optb,
-            COption::None => COption::None,
-        }
-    }
-
-    /// Returns [`COption::None`] if the option is [`COption::None`], otherwise calls `f` with the
-    /// wrapped value and returns the result.
-    ///
-    /// COption::Some languages call this operation flatmap.
-    ///
-    /// [`COption::None`]: #variant.COption::None
-    ///
-    /// # Examples
-    ///
-    /// ```ignore
-    /// fn sq(x: u32) -> COption<u32> { COption::Some(x * x) }
-    /// fn nope(_: u32) -> COption<u32> { COption::None }
-    ///
-    /// assert_eq!(COption::Some(2).and_then(sq).and_then(sq), COption::Some(16));
-    /// assert_eq!(COption::Some(2).and_then(sq).and_then(nope), COption::None);
-    /// assert_eq!(COption::Some(2).and_then(nope).and_then(sq), COption::None);
-    /// assert_eq!(COption::None.and_then(sq).and_then(sq), COption::None);
-    /// ```
-    #[inline]
-    pub fn and_then<U, F: FnOnce(T) -> COption<U>>(self, f: F) -> COption<U> {
-        match self {
-            COption::Some(x) => f(x),
-            COption::None => COption::None,
-        }
-    }
-
-    /// Returns [`COption::None`] if the option is [`COption::None`], otherwise calls `predicate`
-    /// with the wrapped value and returns:
-    ///
-    /// - [`COption::Some(t)`] if `predicate` returns `true` (where `t` is the wrapped
-    ///   value), and
-    /// - [`COption::None`] if `predicate` returns `false`.
-    ///
-    /// This function works similar to [`Iterator::filter()`]. You can imagine
-    /// the `COption<T>` being an iterator over one or zero elements. `filter()`
-    /// lets you decide which elements to keep.
-    ///
-    /// # Examples
-    ///
-    /// ```ignore
-    /// fn is_even(n: &i32) -> bool {
-    ///     n % 2 == 0
-    /// }
-    ///
-    /// assert_eq!(COption::None.filter(is_even), COption::None);
-    /// assert_eq!(COption::Some(3).filter(is_even), COption::None);
-    /// assert_eq!(COption::Some(4).filter(is_even), COption::Some(4));
-    /// ```
-    ///
-    /// [`COption::None`]: #variant.COption::None
-    /// [`COption::Some(t)`]: #variant.COption::Some
-    /// [`Iterator::filter()`]: ../../std/iter/trait.Iterator.html#method.filter
-    #[inline]
-    pub fn filter<P: FnOnce(&T) -> bool>(self, predicate: P) -> Self {
-        if let COption::Some(x) = self {
-            if predicate(&x) {
-                return COption::Some(x);
-            }
-        }
-        COption::None
-    }
-
-    /// Returns the option if it contains a value, otherwise returns `optb`.
-    ///
-    /// Arguments passed to `or` are eagerly evaluated; if you are passing the
-    /// result of a function call, it is recommended to use [`or_else`], which is
-    /// lazily evaluated.
-    ///
-    /// [`or_else`]: #method.or_else
-    ///
-    /// # Examples
-    ///
-    /// ```ignore
-    /// let x = COption::Some(2);
-    /// let y = COption::None;
-    /// assert_eq!(x.or(y), COption::Some(2));
-    ///
-    /// let x = COption::None;
-    /// let y = COption::Some(100);
-    /// assert_eq!(x.or(y), COption::Some(100));
-    ///
-    /// let x = COption::Some(2);
-    /// let y = COption::Some(100);
-    /// assert_eq!(x.or(y), COption::Some(2));
-    ///
-    /// let x: COption<u32> = COption::None;
-    /// let y = COption::None;
-    /// assert_eq!(x.or(y), COption::None);
-    /// ```
-    #[inline]
-    pub fn or(self, optb: COption<T>) -> COption<T> {
-        match self {
-            COption::Some(_) => self,
-            COption::None => optb,
-        }
-    }
-
-    /// Returns the option if it contains a value, otherwise calls `f` and
-    /// returns the result.
-    ///
-    /// # Examples
-    ///
-    /// ```ignore
-    /// fn nobody() -> COption<&'static str> { COption::None }
-    /// fn vikings() -> COption<&'static str> { COption::Some("vikings") }
-    ///
-    /// assert_eq!(COption::Some("barbarians").or_else(vikings), COption::Some("barbarians"));
-    /// assert_eq!(COption::None.or_else(vikings), COption::Some("vikings"));
-    /// assert_eq!(COption::None.or_else(nobody), COption::None);
-    /// ```
-    #[inline]
-    pub fn or_else<F: FnOnce() -> COption<T>>(self, f: F) -> COption<T> {
-        match self {
-            COption::Some(_) => self,
-            COption::None => f(),
-        }
-    }
-
-    /// Returns [`COption::Some`] if exactly one of `self`, `optb` is [`COption::Some`], otherwise returns [`COption::None`].
-    ///
-    /// [`COption::Some`]: #variant.COption::Some
-    /// [`COption::None`]: #variant.COption::None
-    ///
-    /// # Examples
-    ///
-    /// ```ignore
-    /// let x = COption::Some(2);
-    /// let y: COption<u32> = COption::None;
-    /// assert_eq!(x.xor(y), COption::Some(2));
-    ///
-    /// let x: COption<u32> = COption::None;
-    /// let y = COption::Some(2);
-    /// assert_eq!(x.xor(y), COption::Some(2));
-    ///
-    /// let x = COption::Some(2);
-    /// let y = COption::Some(2);
-    /// assert_eq!(x.xor(y), COption::None);
-    ///
-    /// let x: COption<u32> = COption::None;
-    /// let y: COption<u32> = COption::None;
-    /// assert_eq!(x.xor(y), COption::None);
-    /// ```
-    #[inline]
-    pub fn xor(self, optb: COption<T>) -> COption<T> {
-        match (self, optb) {
-            (COption::Some(a), COption::None) => COption::Some(a),
-            (COption::None, COption::Some(b)) => COption::Some(b),
-            _ => COption::None,
-        }
-    }
-
-    /////////////////////////////////////////////////////////////////////////
-    // Entry-like operations to insert if COption::None and return a reference
-    /////////////////////////////////////////////////////////////////////////
-
-    /// Inserts `v` into the option if it is [`COption::None`], then
-    /// returns a mutable reference to the contained value.
-    ///
-    /// [`COption::None`]: #variant.COption::None
-    ///
-    /// # Examples
-    ///
-    /// ```ignore
-    /// let mut x = COption::None;
-    ///
-    /// {
-    ///     let y: &mut u32 = x.get_or_insert(5);
-    ///     assert_eq!(y, &5);
-    ///
-    ///     *y = 7;
-    /// }
-    ///
-    /// assert_eq!(x, COption::Some(7));
-    /// ```
-    #[inline]
-    pub fn get_or_insert(&mut self, v: T) -> &mut T {
-        self.get_or_insert_with(|| v)
-    }
-
-    /// Inserts a value computed from `f` into the option if it is [`COption::None`], then
-    /// returns a mutable reference to the contained value.
-    ///
-    /// [`COption::None`]: #variant.COption::None
-    ///
-    /// # Examples
-    ///
-    /// ```ignore
-    /// let mut x = COption::None;
-    ///
-    /// {
-    ///     let y: &mut u32 = x.get_or_insert_with(|| 5);
-    ///     assert_eq!(y, &5);
-    ///
-    ///     *y = 7;
-    /// }
-    ///
-    /// assert_eq!(x, COption::Some(7));
-    /// ```
-    #[inline]
-    pub fn get_or_insert_with<F: FnOnce() -> T>(&mut self, f: F) -> &mut T {
-        if let COption::None = *self {
-            *self = COption::Some(f())
-        }
-
-        match *self {
-            COption::Some(ref mut v) => v,
-            COption::None => unsafe { hint::unreachable_unchecked() },
-        }
-    }
-
-    /////////////////////////////////////////////////////////////////////////
-    // Misc
-    /////////////////////////////////////////////////////////////////////////
-
-    /// Replaces the actual value in the option by the value given in parameter,
-    /// returning the old value if present,
-    /// leaving a [`COption::Some`] in its place without deinitializing either one.
-    ///
-    /// [`COption::Some`]: #variant.COption::Some
-    ///
-    /// # Examples
-    ///
-    /// ```ignore
-    /// let mut x = COption::Some(2);
-    /// let old = x.replace(5);
-    /// assert_eq!(x, COption::Some(5));
-    /// assert_eq!(old, COption::Some(2));
-    ///
-    /// let mut x = COption::None;
-    /// let old = x.replace(3);
-    /// assert_eq!(x, COption::Some(3));
-    /// assert_eq!(old, COption::None);
-    /// ```
-    #[inline]
-    pub fn replace(&mut self, value: T) -> COption<T> {
-        mem::replace(self, COption::Some(value))
-    }
-}
-
-impl<T: Copy> COption<&T> {
-    /// Maps an `COption<&T>` to an `COption<T>` by copying the contents of the
-    /// option.
-    ///
-    /// # Examples
-    ///
-    /// ```ignore
-    /// let x = 12;
-    /// let opt_x = COption::Some(&x);
-    /// assert_eq!(opt_x, COption::Some(&12));
-    /// let copied = opt_x.copied();
-    /// assert_eq!(copied, COption::Some(12));
-    /// ```
-    pub fn copied(self) -> COption<T> {
-        self.map(|&t| t)
-    }
-}
-
-impl<T: Copy> COption<&mut T> {
-    /// Maps an `COption<&mut T>` to an `COption<T>` by copying the contents of the
-    /// option.
-    ///
-    /// # Examples
-    ///
-    /// ```ignore
-    /// let mut x = 12;
-    /// let opt_x = COption::Some(&mut x);
-    /// assert_eq!(opt_x, COption::Some(&mut 12));
-    /// let copied = opt_x.copied();
-    /// assert_eq!(copied, COption::Some(12));
-    /// ```
-    pub fn copied(self) -> COption<T> {
-        self.map(|&mut t| t)
-    }
-}
-
-impl<T: Clone> COption<&T> {
-    /// Maps an `COption<&T>` to an `COption<T>` by cloning the contents of the
-    /// option.
-    ///
-    /// # Examples
-    ///
-    /// ```ignore
-    /// let x = 12;
-    /// let opt_x = COption::Some(&x);
-    /// assert_eq!(opt_x, COption::Some(&12));
-    /// let cloned = opt_x.cloned();
-    /// assert_eq!(cloned, COption::Some(12));
-    /// ```
-    pub fn cloned(self) -> COption<T> {
-        self.map(|t| t.clone())
-    }
-}
-
-impl<T: Clone> COption<&mut T> {
-    /// Maps an `COption<&mut T>` to an `COption<T>` by cloning the contents of the
-    /// option.
-    ///
-    /// # Examples
-    ///
-    /// ```ignore
-    /// let mut x = 12;
-    /// let opt_x = COption::Some(&mut x);
-    /// assert_eq!(opt_x, COption::Some(&mut 12));
-    /// let cloned = opt_x.cloned();
-    /// assert_eq!(cloned, COption::Some(12));
-    /// ```
-    pub fn cloned(self) -> COption<T> {
-        self.map(|t| t.clone())
-    }
-}
-
-impl<T: Default> COption<T> {
-    /// Returns the contained value or a default
-    ///
-    /// Consumes the `self` argument then, if [`COption::Some`], returns the contained
-    /// value, otherwise if [`COption::None`], returns the [default value] for that
-    /// type.
-    ///
-    /// # Examples
-    ///
-    /// Converts a string to an integer, turning poorly-formed strings
-    /// into 0 (the default value for integers). [`parse`] converts
-    /// a string to any other type that implements [`FromStr`], returning
-    /// [`COption::None`] on error.
-    ///
-    /// ```ignore
-    /// let good_year_from_input = "1909";
-    /// let bad_year_from_input = "190blarg";
-    /// let good_year = good_year_from_input.parse().ok().unwrap_or_default();
-    /// let bad_year = bad_year_from_input.parse().ok().unwrap_or_default();
-    ///
-    /// assert_eq!(1909, good_year);
-    /// assert_eq!(0, bad_year);
-    /// ```
-    ///
-    /// [`COption::Some`]: #variant.COption::Some
-    /// [`COption::None`]: #variant.COption::None
-    /// [default value]: ../default/trait.Default.html#tymethod.default
-    /// [`parse`]: ../../std/primitive.str.html#method.parse
-    /// [`FromStr`]: ../../std/str/trait.FromStr.html
-    #[inline]
-    pub fn unwrap_or_default(self) -> T {
-        match self {
-            COption::Some(x) => x,
-            COption::None => Default::default(),
-        }
-    }
-}
-
-impl<T: Deref> COption<T> {
-    /// Converts from `COption<T>` (or `&COption<T>`) to `COption<&T::Target>`.
-    ///
-    /// Leaves the original COption in-place, creating a new one with a reference
-    /// to the original one, additionally coercing the contents via [`Deref`].
-    ///
-    /// [`Deref`]: ../../std/ops/trait.Deref.html
-    ///
-    /// # Examples
-    ///
-    /// ```ignore
-    /// #![feature(inner_deref)]
-    ///
-    /// let x: COption<String> = COption::Some("hey".to_owned());
-    /// assert_eq!(x.as_deref(), COption::Some("hey"));
-    ///
-    /// let x: COption<String> = COption::None;
-    /// assert_eq!(x.as_deref(), COption::None);
-    /// ```
-    pub fn as_deref(&self) -> COption<&T::Target> {
-        self.as_ref().map(|t| t.deref())
-    }
-}
-
-impl<T: DerefMut> COption<T> {
-    /// Converts from `COption<T>` (or `&mut COption<T>`) to `COption<&mut T::Target>`.
-    ///
-    /// Leaves the original `COption` in-place, creating a new one containing a mutable reference to
-    /// the inner type's `Deref::Target` type.
-    ///
-    /// # Examples
-    ///
-    /// ```ignore
-    /// #![feature(inner_deref)]
-    ///
-    /// let mut x: COption<String> = COption::Some("hey".to_owned());
-    /// assert_eq!(x.as_deref_mut().map(|x| {
-    ///     x.make_ascii_uppercase();
-    ///     x
-    /// }), COption::Some("HEY".to_owned().as_mut_str()));
-    /// ```
-    pub fn as_deref_mut(&mut self) -> COption<&mut T::Target> {
-        self.as_mut().map(|t| t.deref_mut())
-    }
-}
-
-impl<T, E> COption<Result<T, E>> {
-    /// Transposes an `COption` of a [`Result`] into a [`Result`] of an `COption`.
-    ///
-    /// [`COption::None`] will be mapped to [`Ok`]`(`[`COption::None`]`)`.
-    /// [`COption::Some`]`(`[`Ok`]`(_))` and [`COption::Some`]`(`[`Err`]`(_))` will be mapped to
-    /// [`Ok`]`(`[`COption::Some`]`(_))` and [`Err`]`(_)`.
-    ///
-    /// [`COption::None`]: #variant.COption::None
-    /// [`Ok`]: ../../std/result/enum.Result.html#variant.Ok
-    /// [`COption::Some`]: #variant.COption::Some
-    /// [`Err`]: ../../std/result/enum.Result.html#variant.Err
-    ///
-    /// # Examples
-    ///
-    /// ```ignore
-    /// #[derive(Debug, Eq, PartialEq)]
-    /// struct COption::SomeErr;
-    ///
-    /// let x: Result<COption<i32>, COption::SomeErr> = Ok(COption::Some(5));
-    /// let y: COption<Result<i32, COption::SomeErr>> = COption::Some(Ok(5));
-    /// assert_eq!(x, y.transpose());
-    /// ```
-    #[inline]
-    pub fn transpose(self) -> Result<COption<T>, E> {
-        match self {
-            COption::Some(Ok(x)) => Ok(COption::Some(x)),
-            COption::Some(Err(e)) => Err(e),
-            COption::None => Ok(COption::None),
-        }
-    }
-}
-
-// This is a separate function to reduce the code size of .expect() itself.
-#[inline(never)]
-#[cold]
-fn expect_failed(msg: &str) -> ! {
-    panic!("{}", msg)
-}
-
-// // This is a separate function to reduce the code size of .expect_none() itself.
-// #[inline(never)]
-// #[cold]
-// fn expect_none_failed(msg: &str, value: &dyn fmt::Debug) -> ! {
-//     panic!("{}: {:?}", msg, value)
-// }
-
-/////////////////////////////////////////////////////////////////////////////
-// Trait implementations
-/////////////////////////////////////////////////////////////////////////////
-
-impl<T: Clone> Clone for COption<T> {
-    #[inline]
-    fn clone(&self) -> Self {
-        match self {
-            COption::Some(x) => COption::Some(x.clone()),
-            COption::None => COption::None,
-        }
-    }
-
-    #[inline]
-    fn clone_from(&mut self, source: &Self) {
-        match (self, source) {
-            (COption::Some(to), COption::Some(from)) => to.clone_from(from),
-            (to, from) => *to = from.clone(),
-        }
-    }
-}
-
-impl<T> Default for COption<T> {
-    /// Returns [`COption::None`][COption::COption::None].
-    ///
-    /// # Examples
-    ///
-    /// ```ignore
-    /// let opt: COption<u32> = COption::default();
-    /// assert!(opt.is_none());
-    /// ```
-    #[inline]
-    fn default() -> COption<T> {
-        COption::None
-    }
-}
-
-impl<T> From<T> for COption<T> {
-    fn from(val: T) -> COption<T> {
-        COption::Some(val)
-    }
-}
-
-impl<'a, T> From<&'a COption<T>> for COption<&'a T> {
-    fn from(o: &'a COption<T>) -> COption<&'a T> {
-        o.as_ref()
-    }
-}
-
-impl<'a, T> From<&'a mut COption<T>> for COption<&'a mut T> {
-    fn from(o: &'a mut COption<T>) -> COption<&'a mut T> {
-        o.as_mut()
-    }
-}
-
-impl<T> COption<COption<T>> {
-    /// Converts from `COption<COption<T>>` to `COption<T>`
-    ///
-    /// # Examples
-    /// Basic usage:
-    /// ```ignore
-    /// #![feature(option_flattening)]
-    /// let x: COption<COption<u32>> = COption::Some(COption::Some(6));
-    /// assert_eq!(COption::Some(6), x.flatten());
-    ///
-    /// let x: COption<COption<u32>> = COption::Some(COption::None);
-    /// assert_eq!(COption::None, x.flatten());
-    ///
-    /// let x: COption<COption<u32>> = COption::None;
-    /// assert_eq!(COption::None, x.flatten());
-    /// ```
-    /// Flattening once only removes one level of nesting:
-    /// ```ignore
-    /// #![feature(option_flattening)]
-    /// let x: COption<COption<COption<u32>>> = COption::Some(COption::Some(COption::Some(6)));
-    /// assert_eq!(COption::Some(COption::Some(6)), x.flatten());
-    /// assert_eq!(COption::Some(6), x.flatten().flatten());
-    /// ```
-    #[inline]
-    pub fn flatten(self) -> COption<T> {
-        self.and_then(convert::identity)
-    }
-}

+ 0 - 2349
program/src/processor.rs

@@ -1,2349 +0,0 @@
-//! Program state processor
-
-#![cfg(feature = "program")]
-
-use crate::{
-    error::TokenError,
-    instruction::{is_valid_signer_index, TokenInstruction},
-    option::COption,
-    state::{self, Account, Mint, Multisig},
-};
-use num_traits::FromPrimitive;
-use solana_sdk::{
-    account_info::{next_account_info, AccountInfo},
-    decode_error::DecodeError,
-    entrypoint::ProgramResult,
-    info,
-    program_error::{PrintProgramError, ProgramError},
-    pubkey::Pubkey,
-};
-use std::mem::size_of;
-
-/// Program state handler.
-pub struct Processor {}
-impl Processor {
-    /// Processes an [InitializeMint](enum.TokenInstruction.html) instruction.
-    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)?;
-
-        let mut mint_info_data = mint_info.data.borrow_mut();
-        let mut mint: &mut Mint = state::unpack_unchecked(&mut mint_info_data)?;
-        if mint.is_initialized {
-            return Err(TokenError::AlreadyInUse.into());
-        }
-
-        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();
-            let mut dest_account: &mut Account = state::unpack(&mut dest_account_data)?;
-
-            if mint_info.key != &dest_account.mint {
-                return Err(TokenError::MintMismatch.into());
-            }
-
-            dest_account.amount = amount;
-
-            if let Ok(owner_info) = next_account_info(account_info_iter) {
-                COption::Some(*owner_info.key)
-            } else {
-                COption::None
-            }
-        } else if let Ok(owner_info) = next_account_info(account_info_iter) {
-            COption::Some(*owner_info.key)
-        } else {
-            return Err(TokenError::OwnerRequiredIfNoInitialSupply.into());
-        };
-
-        mint.owner = owner;
-        mint.decimals = decimals;
-        mint.is_initialized = true;
-
-        Ok(())
-    }
-
-    /// Processes an [InitializeAccount](enum.TokenInstruction.html) instruction.
-    pub fn process_initialize_account(accounts: &[AccountInfo]) -> ProgramResult {
-        let account_info_iter = &mut accounts.iter();
-        let new_account_info = next_account_info(account_info_iter)?;
-        let mint_info = next_account_info(account_info_iter)?;
-        let owner_info = next_account_info(account_info_iter)?;
-
-        let mut new_account_data = new_account_info.data.borrow_mut();
-        let mut account: &mut Account = state::unpack_unchecked(&mut new_account_data)?;
-        if account.is_initialized {
-            return Err(TokenError::AlreadyInUse.into());
-        }
-
-        account.mint = *mint_info.key;
-        account.owner = *owner_info.key;
-        account.delegate = COption::None;
-        account.delegated_amount = 0;
-        account.is_initialized = true;
-        if *mint_info.key == crate::native_mint::id() {
-            account.is_native = true;
-            account.amount = new_account_info.lamports();
-        } else {
-            account.is_native = false;
-            account.amount = 0;
-        };
-
-        Ok(())
-    }
-
-    /// Processes a [InitializeMultisig](enum.TokenInstruction.html) instruction.
-    pub fn process_initialize_multisig(accounts: &[AccountInfo], m: u8) -> ProgramResult {
-        let account_info_iter = &mut accounts.iter();
-        let multisig_info = next_account_info(account_info_iter)?;
-        let mut multisig_account_data = multisig_info.data.borrow_mut();
-        let mut multisig: &mut Multisig = state::unpack_unchecked(&mut multisig_account_data)?;
-        if multisig.is_initialized {
-            return Err(TokenError::AlreadyInUse.into());
-        }
-
-        let signer_infos = account_info_iter.as_slice();
-        multisig.m = m;
-        multisig.n = signer_infos.len() as u8;
-        if !is_valid_signer_index(multisig.n as usize) {
-            return Err(TokenError::InvalidNumberOfProvidedSigners.into());
-        }
-        if !is_valid_signer_index(multisig.m as usize) {
-            return Err(TokenError::InvalidNumberOfRequiredSigners.into());
-        }
-        for (i, signer_info) in signer_infos.iter().enumerate() {
-            multisig.signers[i] = *signer_info.key;
-        }
-        multisig.is_initialized = true;
-
-        Ok(())
-    }
-
-    /// Processes a [Transfer](enum.TokenInstruction.html) instruction.
-    pub fn process_transfer(
-        program_id: &Pubkey,
-        accounts: &[AccountInfo],
-        amount: u64,
-    ) -> ProgramResult {
-        let account_info_iter = &mut accounts.iter();
-        let source_account_info = next_account_info(account_info_iter)?;
-        let dest_account_info = next_account_info(account_info_iter)?;
-        let authority_info = next_account_info(account_info_iter)?;
-
-        let mut source_data = source_account_info.data.borrow_mut();
-        let mut source_account: &mut Account = state::unpack(&mut source_data)?;
-        let mut dest_data = dest_account_info.data.borrow_mut();
-        let mut dest_account: &mut Account = state::unpack(&mut dest_data)?;
-
-        if source_account.amount < amount {
-            return Err(TokenError::InsufficientFunds.into());
-        }
-        if source_account.mint != dest_account.mint {
-            return Err(TokenError::MintMismatch.into());
-        }
-
-        match source_account.delegate {
-            COption::Some(ref delegate) if authority_info.key == delegate => {
-                Self::validate_owner(
-                    program_id,
-                    delegate,
-                    authority_info,
-                    account_info_iter.as_slice(),
-                )?;
-                if source_account.delegated_amount < amount {
-                    return Err(TokenError::InsufficientFunds.into());
-                }
-                source_account.delegated_amount -= amount;
-                if source_account.delegated_amount == 0 {
-                    source_account.delegate = COption::None;
-                }
-            }
-            _ => Self::validate_owner(
-                program_id,
-                &source_account.owner,
-                authority_info,
-                account_info_iter.as_slice(),
-            )?,
-        };
-
-        source_account.amount -= amount;
-        dest_account.amount = dest_account
-            .amount
-            .checked_add(amount)
-            .ok_or(TokenError::Overflow)?;
-
-        if source_account.is_native {
-            **source_account_info.lamports.borrow_mut() -= amount;
-            **dest_account_info.lamports.borrow_mut() += amount;
-        }
-
-        Ok(())
-    }
-
-    /// Processes an [Approve](enum.TokenInstruction.html) instruction.
-    pub fn process_approve(
-        program_id: &Pubkey,
-        accounts: &[AccountInfo],
-        amount: u64,
-    ) -> ProgramResult {
-        let account_info_iter = &mut accounts.iter();
-        let source_account_info = next_account_info(account_info_iter)?;
-
-        let mut source_data = source_account_info.data.borrow_mut();
-        let mut source_account: &mut Account = state::unpack(&mut source_data)?;
-        let delegate_info = next_account_info(account_info_iter)?;
-        let owner_info = next_account_info(account_info_iter)?;
-
-        Self::validate_owner(
-            program_id,
-            &source_account.owner,
-            owner_info,
-            account_info_iter.as_slice(),
-        )?;
-
-        source_account.delegate = COption::Some(*delegate_info.key);
-        source_account.delegated_amount = amount;
-
-        Ok(())
-    }
-
-    /// Processes an [Revoke](enum.TokenInstruction.html) instruction.
-    pub fn process_revoke(program_id: &Pubkey, accounts: &[AccountInfo]) -> ProgramResult {
-        let account_info_iter = &mut accounts.iter();
-        let source_account_info = next_account_info(account_info_iter)?;
-
-        let mut source_data = source_account_info.data.borrow_mut();
-        let mut source_account: &mut Account = state::unpack(&mut source_data)?;
-        let owner_info = next_account_info(account_info_iter)?;
-
-        Self::validate_owner(
-            program_id,
-            &source_account.owner,
-            owner_info,
-            account_info_iter.as_slice(),
-        )?;
-
-        source_account.delegate = COption::None;
-        source_account.delegated_amount = 0;
-
-        Ok(())
-    }
-
-    /// Processes a [SetOwner](enum.TokenInstruction.html) instruction.
-    pub fn process_set_owner(program_id: &Pubkey, accounts: &[AccountInfo]) -> ProgramResult {
-        let account_info_iter = &mut accounts.iter();
-        let account_info = next_account_info(account_info_iter)?;
-        let new_owner_info = next_account_info(account_info_iter)?;
-        let authority_info = next_account_info(account_info_iter)?;
-
-        if account_info.data_len() == size_of::<Account>() {
-            let mut account_data = account_info.data.borrow_mut();
-            let mut account: &mut Account = state::unpack(&mut account_data)?;
-
-            Self::validate_owner(
-                program_id,
-                &account.owner,
-                authority_info,
-                account_info_iter.as_slice(),
-            )?;
-
-            account.owner = *new_owner_info.key;
-        } else if account_info.data_len() == size_of::<Mint>() {
-            let mut account_data = account_info.data.borrow_mut();
-            let mut mint: &mut Mint = state::unpack(&mut account_data)?;
-
-            match mint.owner {
-                COption::Some(ref owner) => {
-                    Self::validate_owner(
-                        program_id,
-                        owner,
-                        authority_info,
-                        account_info_iter.as_slice(),
-                    )?;
-                }
-                COption::None => return Err(TokenError::FixedSupply.into()),
-            }
-            mint.owner = COption::Some(*new_owner_info.key);
-        } else {
-            return Err(ProgramError::InvalidArgument);
-        }
-
-        Ok(())
-    }
-
-    /// Processes a [MintTo](enum.TokenInstruction.html) instruction.
-    pub fn process_mint_to(
-        program_id: &Pubkey,
-        accounts: &[AccountInfo],
-        amount: u64,
-    ) -> ProgramResult {
-        let account_info_iter = &mut accounts.iter();
-        let mint_info = next_account_info(account_info_iter)?;
-        let dest_account_info = next_account_info(account_info_iter)?;
-        let owner_info = next_account_info(account_info_iter)?;
-
-        let mut dest_account_data = dest_account_info.data.borrow_mut();
-        let mut dest_account: &mut Account = state::unpack(&mut dest_account_data)?;
-
-        if dest_account.is_native {
-            return Err(TokenError::NativeNotSupported.into());
-        }
-        if mint_info.key != &dest_account.mint {
-            return Err(TokenError::MintMismatch.into());
-        }
-
-        let mut mint_info_data = mint_info.data.borrow_mut();
-        let mint: &mut Mint = state::unpack(&mut mint_info_data)?;
-
-        match mint.owner {
-            COption::Some(owner) => {
-                Self::validate_owner(program_id, &owner, owner_info, account_info_iter.as_slice())?;
-            }
-            COption::None => {
-                return Err(TokenError::FixedSupply.into());
-            }
-        }
-
-        dest_account.amount = dest_account
-            .amount
-            .checked_add(amount)
-            .ok_or(TokenError::Overflow)?;
-
-        Ok(())
-    }
-
-    /// Processes a [Burn](enum.TokenInstruction.html) instruction.
-    pub fn process_burn(
-        program_id: &Pubkey,
-        accounts: &[AccountInfo],
-        amount: u64,
-    ) -> ProgramResult {
-        let account_info_iter = &mut accounts.iter();
-        let source_account_info = next_account_info(account_info_iter)?;
-        let authority_info = next_account_info(account_info_iter)?;
-
-        let mut source_data = source_account_info.data.borrow_mut();
-        let source_account: &mut Account = state::unpack(&mut source_data)?;
-
-        if source_account.is_native {
-            return Err(TokenError::NativeNotSupported.into());
-        }
-        if source_account.amount < amount {
-            return Err(TokenError::InsufficientFunds.into());
-        }
-
-        match source_account.delegate {
-            COption::Some(ref delegate) if authority_info.key == delegate => {
-                Self::validate_owner(
-                    program_id,
-                    delegate,
-                    authority_info,
-                    account_info_iter.as_slice(),
-                )?;
-
-                if source_account.delegated_amount < amount {
-                    return Err(TokenError::InsufficientFunds.into());
-                }
-                source_account.delegated_amount -= amount;
-                if source_account.delegated_amount == 0 {
-                    source_account.delegate = COption::None;
-                }
-            }
-            _ => Self::validate_owner(
-                program_id,
-                &source_account.owner,
-                authority_info,
-                account_info_iter.as_slice(),
-            )?,
-        }
-
-        source_account.amount -= amount;
-
-        Ok(())
-    }
-
-    /// Processes a [CloseAccount](enum.TokenInstruction.html) instruction.
-    pub fn process_close_account(program_id: &Pubkey, accounts: &[AccountInfo]) -> ProgramResult {
-        let account_info_iter = &mut accounts.iter();
-        let source_account_info = next_account_info(account_info_iter)?;
-        let dest_account_info = next_account_info(account_info_iter)?;
-        let authority_info = next_account_info(account_info_iter)?;
-
-        let mut source_data = source_account_info.data.borrow_mut();
-        let source_account: &mut Account = state::unpack(&mut source_data)?;
-
-        if !source_account.is_native {
-            return Err(TokenError::NonNativeNotSupported.into());
-        }
-
-        Self::validate_owner(
-            program_id,
-            &source_account.owner,
-            authority_info,
-            account_info_iter.as_slice(),
-        )?;
-
-        **dest_account_info.lamports.borrow_mut() += source_account_info.lamports();
-        **source_account_info.lamports.borrow_mut() = 0;
-        source_account.amount = 0;
-
-        Ok(())
-    }
-
-    /// Processes an [Instruction](enum.Instruction.html).
-    pub fn process(program_id: &Pubkey, accounts: &[AccountInfo], input: &[u8]) -> ProgramResult {
-        let instruction = TokenInstruction::unpack(input)?;
-
-        match instruction {
-            TokenInstruction::InitializeMint { amount, decimals } => {
-                info!("Instruction: InitializeMint");
-                Self::process_initialize_mint(accounts, amount, decimals)
-            }
-            TokenInstruction::InitializeAccount => {
-                info!("Instruction: InitializeAccount");
-                Self::process_initialize_account(accounts)
-            }
-            TokenInstruction::InitializeMultisig { m } => {
-                info!("Instruction: InitializeMultisig");
-                Self::process_initialize_multisig(accounts, m)
-            }
-            TokenInstruction::Transfer { amount } => {
-                info!("Instruction: Transfer");
-                Self::process_transfer(program_id, accounts, amount)
-            }
-            TokenInstruction::Approve { amount } => {
-                info!("Instruction: Approve");
-                Self::process_approve(program_id, accounts, amount)
-            }
-            TokenInstruction::Revoke => {
-                info!("Instruction: Revoke");
-                Self::process_revoke(program_id, accounts)
-            }
-            TokenInstruction::SetOwner => {
-                info!("Instruction: SetOwner");
-                Self::process_set_owner(program_id, accounts)
-            }
-            TokenInstruction::MintTo { amount } => {
-                info!("Instruction: MintTo");
-                Self::process_mint_to(program_id, accounts, amount)
-            }
-            TokenInstruction::Burn { amount } => {
-                info!("Instruction: Burn");
-                Self::process_burn(program_id, accounts, amount)
-            }
-            TokenInstruction::CloseAccount => {
-                info!("Instruction: CloseAccount");
-                Self::process_close_account(program_id, accounts)
-            }
-        }
-    }
-
-    /// Validates owner(s) are present
-    pub fn validate_owner(
-        program_id: &Pubkey,
-        expected_owner: &Pubkey,
-        owner_account_info: &AccountInfo,
-        signers: &[AccountInfo],
-    ) -> ProgramResult {
-        if expected_owner != owner_account_info.key {
-            return Err(TokenError::OwnerMismatch.into());
-        }
-        if program_id == owner_account_info.owner
-            && owner_account_info.data_len() == std::mem::size_of::<Multisig>()
-        {
-            let mut owner_data = owner_account_info.data.borrow_mut();
-            let multisig: &mut Multisig = state::unpack(&mut owner_data)?;
-            let mut num_signers = 0;
-            for signer in signers.iter() {
-                if multisig.signers[0..multisig.n as usize].contains(signer.key) {
-                    if !signer.is_signer {
-                        return Err(ProgramError::MissingRequiredSignature);
-                    }
-                    num_signers += 1;
-                }
-            }
-            if num_signers < multisig.m {
-                return Err(ProgramError::MissingRequiredSignature);
-            }
-        } else if !owner_account_info.is_signer {
-            return Err(ProgramError::MissingRequiredSignature);
-        }
-        Ok(())
-    }
-}
-
-impl PrintProgramError for TokenError {
-    fn print<E>(&self)
-    where
-        E: 'static + std::error::Error + DecodeError<E> + PrintProgramError + FromPrimitive,
-    {
-        match self {
-            TokenError::InsufficientFunds => info!("Error: insufficient funds"),
-            TokenError::MintMismatch => info!("Error: Account not associated with this Mint"),
-            TokenError::OwnerMismatch => info!("Error: owner does not match"),
-            TokenError::FixedSupply => info!("Error: the total supply of this token is fixed"),
-            TokenError::AlreadyInUse => info!("Error: account or token already in use"),
-            TokenError::OwnerRequiredIfNoInitialSupply => {
-                info!("Error: An owner is required if supply is zero")
-            }
-            TokenError::InvalidNumberOfProvidedSigners => {
-                info!("Error: Invalid number of provided signers")
-            }
-            TokenError::InvalidNumberOfRequiredSigners => {
-                info!("Error: Invalid number of required signers")
-            }
-            TokenError::UninitializedState => info!("Error: State is uninitialized"),
-            TokenError::NativeNotSupported => {
-                info!("Error: Instruction does not support native tokens")
-            }
-            TokenError::NonNativeNotSupported => {
-                info!("Error: Instruction does not support non-native tokens")
-            }
-            TokenError::InvalidInstruction => info!("Error: Invalid instruction"),
-            TokenError::Overflow => info!("Error: Operation overflowed"),
-        }
-    }
-}
-
-// Pull in syscall stubs when building for non-BPF targets
-#[cfg(not(target_arch = "bpf"))]
-solana_sdk::program_stubs!();
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-    use crate::instruction::{
-        approve, burn, close_account, initialize_account, initialize_mint, initialize_multisig,
-        mint_to, revoke, set_owner, transfer, MAX_SIGNERS,
-    };
-    use solana_sdk::{
-        account::Account as SolanaAccount, account_info::create_is_signer_account_infos,
-        clock::Epoch, instruction::Instruction,
-    };
-
-    fn pubkey_rand() -> Pubkey {
-        Pubkey::new(&rand::random::<[u8; 32]>())
-    }
-
-    fn do_process_instruction(
-        instruction: Instruction,
-        accounts: Vec<&mut SolanaAccount>,
-    ) -> ProgramResult {
-        let mut meta = instruction
-            .accounts
-            .iter()
-            .zip(accounts)
-            .map(|(account_meta, account)| (&account_meta.pubkey, account_meta.is_signer, account))
-            .collect::<Vec<_>>();
-
-        let account_infos = create_is_signer_account_infos(&mut meta);
-        Processor::process(&instruction.program_id, &account_infos, &instruction.data)
-    }
-
-    fn return_token_error_as_program_error() -> ProgramError {
-        TokenError::MintMismatch.into()
-    }
-
-    #[test]
-    fn test_print_error() {
-        let error = return_token_error_as_program_error();
-        error.print::<TokenError>();
-    }
-
-    #[test]
-    #[should_panic(expected = "Custom(1)")]
-    fn test_error_unwrap() {
-        Err::<(), ProgramError>(return_token_error_as_program_error()).unwrap();
-    }
-
-    #[test]
-    fn test_unique_account_sizes() {
-        assert_ne!(size_of::<Mint>(), 0);
-        assert_ne!(size_of::<Mint>(), size_of::<Account>());
-        assert_ne!(size_of::<Mint>(), size_of::<Multisig>());
-        assert_ne!(size_of::<Account>(), 0);
-        assert_ne!(size_of::<Account>(), size_of::<Multisig>());
-        assert_ne!(size_of::<Multisig>(), 0);
-    }
-
-    #[test]
-    fn test_initialize_mint() {
-        let program_id = pubkey_rand();
-        let account_key = pubkey_rand();
-        let mut account_account = SolanaAccount::new(0, size_of::<Account>(), &program_id);
-        let account2_key = pubkey_rand();
-        let mut account2_account = SolanaAccount::new(0, size_of::<Account>(), &program_id);
-        let owner_key = pubkey_rand();
-        let mut owner_account = SolanaAccount::default();
-        let mint_key = pubkey_rand();
-        let mut mint_account = SolanaAccount::new(0, size_of::<Mint>(), &program_id);
-        let mint2_key = pubkey_rand();
-        let mut mint2_account = SolanaAccount::new(0, size_of::<Mint>(), &program_id);
-
-        // account not created
-        assert_eq!(
-            Err(TokenError::UninitializedState.into()),
-            do_process_instruction(
-                initialize_mint(&program_id, &mint_key, Some(&account_key), None, 1000, 2).unwrap(),
-                vec![&mut mint_account, &mut account_account]
-            )
-        );
-
-        // create account
-        do_process_instruction(
-            initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
-            vec![&mut account_account, &mut owner_account, &mut mint_account],
-        )
-        .unwrap();
-
-        // create new mint
-        do_process_instruction(
-            initialize_mint(&program_id, &mint_key, Some(&account_key), None, 1000, 2).unwrap(),
-            vec![&mut mint_account, &mut account_account],
-        )
-        .unwrap();
-
-        // create another account
-        do_process_instruction(
-            initialize_account(&program_id, &account2_key, &mint_key, &owner_key).unwrap(),
-            vec![&mut account2_account, &mut owner_account, &mut mint_account],
-        )
-        .unwrap();
-
-        // mismatch account
-        assert_eq!(
-            Err(TokenError::MintMismatch.into()),
-            do_process_instruction(
-                initialize_mint(&program_id, &mint2_key, Some(&account2_key), None, 1000, 2)
-                    .unwrap(),
-                vec![&mut mint2_account, &mut account2_account]
-            )
-        );
-
-        // create twice
-        assert_eq!(
-            Err(TokenError::AlreadyInUse.into()),
-            do_process_instruction(
-                initialize_mint(&program_id, &mint_key, Some(&account_key), None, 1000, 2).unwrap(),
-                vec![&mut mint_account, &mut account_account]
-            )
-        );
-    }
-
-    #[test]
-    fn test_initialize_mint_account() {
-        let program_id = pubkey_rand();
-        let account_key = pubkey_rand();
-        let mut account_account = SolanaAccount::new(0, size_of::<Account>(), &program_id);
-        let owner_key = pubkey_rand();
-        let mut owner_account = SolanaAccount::default();
-        let mint_key = pubkey_rand();
-        let mut mint_account = SolanaAccount::new(0, size_of::<Mint>(), &program_id);
-
-        // create account
-        do_process_instruction(
-            initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
-            vec![&mut account_account, &mut mint_account, &mut owner_account],
-        )
-        .unwrap();
-
-        // create twice
-        assert_eq!(
-            Err(TokenError::AlreadyInUse.into()),
-            do_process_instruction(
-                initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
-                vec![&mut account_account, &mut mint_account, &mut owner_account],
-            )
-        );
-    }
-
-    #[test]
-    fn test_transfer() {
-        let program_id = pubkey_rand();
-        let account_key = pubkey_rand();
-        let mut account_account = SolanaAccount::new(0, size_of::<Account>(), &program_id);
-        let account2_key = pubkey_rand();
-        let mut account2_account = SolanaAccount::new(0, size_of::<Account>(), &program_id);
-        let account3_key = pubkey_rand();
-        let mut account3_account = SolanaAccount::new(0, size_of::<Account>(), &program_id);
-        let delegate_key = pubkey_rand();
-        let mut delegate_account = SolanaAccount::default();
-        let mismatch_key = pubkey_rand();
-        let mut mismatch_account = SolanaAccount::new(0, size_of::<Account>(), &program_id);
-        let owner_key = pubkey_rand();
-        let mut owner_account = SolanaAccount::default();
-        let owner2_key = pubkey_rand();
-        let mut owner2_account = SolanaAccount::default();
-        let mint_key = pubkey_rand();
-        let mut mint_account = SolanaAccount::new(0, size_of::<Mint>(), &program_id);
-        let mint2_key = pubkey_rand();
-        let mut mint2_account = SolanaAccount::new(0, size_of::<Mint>(), &program_id);
-
-        // create account
-        do_process_instruction(
-            initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
-            vec![&mut account_account, &mut mint_account, &mut owner_account],
-        )
-        .unwrap();
-
-        // create another account
-        do_process_instruction(
-            initialize_account(&program_id, &account2_key, &mint_key, &owner_key).unwrap(),
-            vec![&mut account2_account, &mut mint_account, &mut owner_account],
-        )
-        .unwrap();
-
-        // create another account
-        do_process_instruction(
-            initialize_account(&program_id, &account3_key, &mint_key, &owner_key).unwrap(),
-            vec![&mut account3_account, &mut mint_account, &mut owner_account],
-        )
-        .unwrap();
-
-        // create mismatch account
-        do_process_instruction(
-            initialize_account(&program_id, &mismatch_key, &mint2_key, &owner_key).unwrap(),
-            vec![
-                &mut mismatch_account,
-                &mut mint2_account,
-                &mut owner_account,
-            ],
-        )
-        .unwrap();
-
-        // create new mint
-        do_process_instruction(
-            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 = transfer(
-            &program_id,
-            &account_key,
-            &account2_key,
-            &owner_key,
-            &[],
-            1000,
-        )
-        .unwrap();
-        instruction.accounts[2].is_signer = false;
-        assert_eq!(
-            Err(ProgramError::MissingRequiredSignature),
-            do_process_instruction(
-                instruction,
-                vec![
-                    &mut account_account,
-                    &mut account2_account,
-                    &mut owner_account,
-                ],
-            )
-        );
-
-        // mismatch mint
-        assert_eq!(
-            Err(TokenError::MintMismatch.into()),
-            do_process_instruction(
-                transfer(
-                    &program_id,
-                    &account_key,
-                    &mismatch_key,
-                    &owner_key,
-                    &[],
-                    1000
-                )
-                .unwrap(),
-                vec![
-                    &mut account_account,
-                    &mut mismatch_account,
-                    &mut owner_account,
-                ],
-            )
-        );
-
-        // missing owner
-        assert_eq!(
-            Err(TokenError::OwnerMismatch.into()),
-            do_process_instruction(
-                transfer(
-                    &program_id,
-                    &account_key,
-                    &account2_key,
-                    &owner2_key,
-                    &[],
-                    1000
-                )
-                .unwrap(),
-                vec![
-                    &mut account_account,
-                    &mut account2_account,
-                    &mut owner2_account,
-                ],
-            )
-        );
-
-        // transfer
-        do_process_instruction(
-            transfer(
-                &program_id,
-                &account_key,
-                &account2_key,
-                &owner_key,
-                &[],
-                1000,
-            )
-            .unwrap(),
-            vec![
-                &mut account_account,
-                &mut account2_account,
-                &mut owner_account,
-            ],
-        )
-        .unwrap();
-
-        // insufficient funds
-        assert_eq!(
-            Err(TokenError::InsufficientFunds.into()),
-            do_process_instruction(
-                transfer(&program_id, &account_key, &account2_key, &owner_key, &[], 1).unwrap(),
-                vec![
-                    &mut account_account,
-                    &mut account2_account,
-                    &mut owner_account,
-                ],
-            )
-        );
-
-        // transfer half back
-        do_process_instruction(
-            transfer(
-                &program_id,
-                &account2_key,
-                &account_key,
-                &owner_key,
-                &[],
-                500,
-            )
-            .unwrap(),
-            vec![
-                &mut account2_account,
-                &mut account_account,
-                &mut owner_account,
-            ],
-        )
-        .unwrap();
-
-        // transfer rest
-        do_process_instruction(
-            transfer(
-                &program_id,
-                &account2_key,
-                &account_key,
-                &owner_key,
-                &[],
-                500,
-            )
-            .unwrap(),
-            vec![
-                &mut account2_account,
-                &mut account_account,
-                &mut owner_account,
-            ],
-        )
-        .unwrap();
-
-        // insufficient funds
-        assert_eq!(
-            Err(TokenError::InsufficientFunds.into()),
-            do_process_instruction(
-                transfer(&program_id, &account2_key, &account_key, &owner_key, &[], 1).unwrap(),
-                vec![
-                    &mut account2_account,
-                    &mut account_account,
-                    &mut owner_account,
-                ],
-            )
-        );
-
-        // approve delegate
-        do_process_instruction(
-            approve(
-                &program_id,
-                &account_key,
-                &delegate_key,
-                &owner_key,
-                &[],
-                100,
-            )
-            .unwrap(),
-            vec![
-                &mut account_account,
-                &mut delegate_account,
-                &mut owner_account,
-            ],
-        )
-        .unwrap();
-
-        // transfer via delegate
-        do_process_instruction(
-            transfer(
-                &program_id,
-                &account_key,
-                &account2_key,
-                &delegate_key,
-                &[],
-                100,
-            )
-            .unwrap(),
-            vec![
-                &mut account_account,
-                &mut account2_account,
-                &mut delegate_account,
-            ],
-        )
-        .unwrap();
-
-        // insufficient funds approved via delegate
-        assert_eq!(
-            Err(TokenError::OwnerMismatch.into()),
-            do_process_instruction(
-                transfer(
-                    &program_id,
-                    &account_key,
-                    &account2_key,
-                    &delegate_key,
-                    &[],
-                    100
-                )
-                .unwrap(),
-                vec![
-                    &mut account_account,
-                    &mut account2_account,
-                    &mut delegate_account,
-                ],
-            )
-        );
-
-        // transfer rest
-        do_process_instruction(
-            transfer(
-                &program_id,
-                &account_key,
-                &account2_key,
-                &owner_key,
-                &[],
-                900,
-            )
-            .unwrap(),
-            vec![
-                &mut account_account,
-                &mut account2_account,
-                &mut owner_account,
-            ],
-        )
-        .unwrap();
-
-        // approve delegate
-        do_process_instruction(
-            approve(
-                &program_id,
-                &account_key,
-                &delegate_key,
-                &owner_key,
-                &[],
-                100,
-            )
-            .unwrap(),
-            vec![
-                &mut account_account,
-                &mut delegate_account,
-                &mut owner_account,
-            ],
-        )
-        .unwrap();
-
-        // insufficient funds in source account via delegate
-        assert_eq!(
-            Err(TokenError::InsufficientFunds.into()),
-            do_process_instruction(
-                transfer(
-                    &program_id,
-                    &account_key,
-                    &account2_key,
-                    &delegate_key,
-                    &[],
-                    100
-                )
-                .unwrap(),
-                vec![
-                    &mut account_account,
-                    &mut account2_account,
-                    &mut delegate_account,
-                ],
-            )
-        );
-    }
-
-    #[test]
-    fn test_mintable_token_with_zero_supply() {
-        let program_id = pubkey_rand();
-        let account_key = pubkey_rand();
-        let mut account_account = SolanaAccount::new(0, size_of::<Account>(), &program_id);
-        let owner_key = pubkey_rand();
-        let mut owner_account = SolanaAccount::default();
-        let mint_key = pubkey_rand();
-        let mut mint_account = SolanaAccount::new(0, size_of::<Mint>(), &program_id);
-
-        // create account
-        do_process_instruction(
-            initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
-            vec![&mut account_account, &mut owner_account, &mut mint_account],
-        )
-        .unwrap();
-
-        // create mint-able token without owner
-        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()),
-            do_process_instruction(instruction, vec![&mut mint_account])
-        );
-
-        // create mint-able token with zero supply
-        let amount = 0;
-        let decimals = 2;
-        do_process_instruction(
-            initialize_mint(
-                &program_id,
-                &mint_key,
-                None,
-                Some(&owner_key),
-                amount,
-                decimals,
-            )
-            .unwrap(),
-            vec![&mut mint_account, &mut account_account],
-        )
-        .unwrap();
-        let mint: &mut Mint = state::unpack(&mut mint_account.data).unwrap();
-        assert_eq!(
-            *mint,
-            Mint {
-                owner: COption::Some(owner_key),
-                decimals,
-                is_initialized: true,
-            }
-        );
-
-        // mint to
-        do_process_instruction(
-            mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 42).unwrap(),
-            vec![&mut mint_account, &mut account_account, &mut owner_account],
-        )
-        .unwrap();
-
-        let _: &mut Mint = state::unpack(&mut mint_account.data).unwrap();
-        let dest_account: &mut Account = state::unpack(&mut account_account.data).unwrap();
-        assert_eq!(dest_account.amount, 42);
-    }
-
-    #[test]
-    fn test_approve() {
-        let program_id = pubkey_rand();
-        let account_key = pubkey_rand();
-        let mut account_account = SolanaAccount::new(0, size_of::<Account>(), &program_id);
-        let account2_key = pubkey_rand();
-        let mut account2_account = SolanaAccount::new(0, size_of::<Account>(), &program_id);
-        let delegate_key = pubkey_rand();
-        let mut delegate_account = SolanaAccount::default();
-        let owner_key = pubkey_rand();
-        let mut owner_account = SolanaAccount::default();
-        let owner2_key = pubkey_rand();
-        let mut owner2_account = SolanaAccount::default();
-        let mint_key = pubkey_rand();
-        let mut mint_account = SolanaAccount::new(0, size_of::<Mint>(), &program_id);
-
-        // create account
-        do_process_instruction(
-            initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
-            vec![&mut account_account, &mut owner_account, &mut mint_account],
-        )
-        .unwrap();
-
-        // create another account
-        do_process_instruction(
-            initialize_account(&program_id, &account2_key, &mint_key, &owner_key).unwrap(),
-            vec![&mut account2_account, &mut owner_account, &mut mint_account],
-        )
-        .unwrap();
-
-        // create new mint
-        do_process_instruction(
-            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 = approve(
-            &program_id,
-            &account_key,
-            &delegate_key,
-            &owner_key,
-            &[],
-            100,
-        )
-        .unwrap();
-        instruction.accounts[2].is_signer = false;
-        assert_eq!(
-            Err(ProgramError::MissingRequiredSignature),
-            do_process_instruction(
-                instruction,
-                vec![
-                    &mut account_account,
-                    &mut delegate_account,
-                    &mut owner_account,
-                ],
-            )
-        );
-
-        // no owner
-        assert_eq!(
-            Err(TokenError::OwnerMismatch.into()),
-            do_process_instruction(
-                approve(
-                    &program_id,
-                    &account_key,
-                    &delegate_key,
-                    &owner2_key,
-                    &[],
-                    100
-                )
-                .unwrap(),
-                vec![
-                    &mut account_account,
-                    &mut delegate_account,
-                    &mut owner2_account,
-                ],
-            )
-        );
-
-        // approve delegate
-        do_process_instruction(
-            approve(
-                &program_id,
-                &account_key,
-                &delegate_key,
-                &owner_key,
-                &[],
-                100,
-            )
-            .unwrap(),
-            vec![
-                &mut account_account,
-                &mut delegate_account,
-                &mut owner_account,
-            ],
-        )
-        .unwrap();
-
-        // revoke delegate
-        do_process_instruction(
-            revoke(&program_id, &account_key, &owner_key, &[]).unwrap(),
-            vec![&mut account_account, &mut owner_account],
-        )
-        .unwrap();
-    }
-
-    #[test]
-    fn test_set_owner() {
-        let program_id = pubkey_rand();
-        let account_key = pubkey_rand();
-        let mut account_account = SolanaAccount::new(0, size_of::<Account>(), &program_id);
-        let account2_key = pubkey_rand();
-        let mut account2_account = SolanaAccount::new(0, size_of::<Account>(), &program_id);
-        let owner_key = pubkey_rand();
-        let mut owner_account = SolanaAccount::default();
-        let owner2_key = pubkey_rand();
-        let mut owner2_account = SolanaAccount::default();
-        let owner3_key = pubkey_rand();
-        let mut owner3_account = SolanaAccount::default();
-        let mint_key = pubkey_rand();
-        let mut mint_account = SolanaAccount::new(0, size_of::<Mint>(), &program_id);
-        let mint2_key = pubkey_rand();
-        let mut mint2_account = SolanaAccount::new(0, size_of::<Mint>(), &program_id);
-
-        // invalid account
-        assert_eq!(
-            Err(TokenError::UninitializedState.into()),
-            do_process_instruction(
-                set_owner(&program_id, &account_key, &owner2_key, &owner_key, &[]).unwrap(),
-                vec![
-                    &mut account_account,
-                    &mut owner2_account,
-                    &mut owner_account,
-                ],
-            )
-        );
-
-        // create account
-        do_process_instruction(
-            initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
-            vec![&mut account_account, &mut mint_account, &mut owner_account],
-        )
-        .unwrap();
-
-        // create another account
-        do_process_instruction(
-            initialize_account(&program_id, &account2_key, &mint2_key, &owner_key).unwrap(),
-            vec![
-                &mut account2_account,
-                &mut mint2_account,
-                &mut owner_account,
-            ],
-        )
-        .unwrap();
-
-        // missing owner
-        assert_eq!(
-            Err(TokenError::OwnerMismatch.into()),
-            do_process_instruction(
-                set_owner(&program_id, &account_key, &owner_key, &owner2_key, &[]).unwrap(),
-                vec![
-                    &mut account_account,
-                    &mut owner_account,
-                    &mut owner2_account,
-                ],
-            )
-        );
-
-        // owner did not sign
-        let mut instruction =
-            set_owner(&program_id, &account_key, &owner2_key, &owner_key, &[]).unwrap();
-        instruction.accounts[2].is_signer = false;
-        assert_eq!(
-            Err(ProgramError::MissingRequiredSignature),
-            do_process_instruction(
-                instruction,
-                vec![
-                    &mut account_account,
-                    &mut owner2_account,
-                    &mut owner_account,
-                ],
-            )
-        );
-
-        // set owner
-        do_process_instruction(
-            set_owner(&program_id, &account_key, &owner2_key, &owner_key, &[]).unwrap(),
-            vec![
-                &mut account_account,
-                &mut owner2_account,
-                &mut owner_account,
-            ],
-        )
-        .unwrap();
-
-        // create new mint with owner
-        do_process_instruction(
-            initialize_mint(
-                &program_id,
-                &mint_key,
-                Some(&account_key),
-                Some(&owner_key),
-                1000,
-                2,
-            )
-            .unwrap(),
-            vec![&mut mint_account, &mut account_account, &mut owner_account],
-        )
-        .unwrap();
-
-        // wrong account
-        assert_eq!(
-            Err(TokenError::OwnerMismatch.into()),
-            do_process_instruction(
-                set_owner(&program_id, &mint_key, &owner3_key, &owner2_key, &[]).unwrap(),
-                vec![&mut mint_account, &mut owner3_account, &mut owner2_account],
-            )
-        );
-
-        // owner did not sign
-        let mut instruction =
-            set_owner(&program_id, &mint_key, &owner2_key, &owner_key, &[]).unwrap();
-        instruction.accounts[2].is_signer = false;
-        assert_eq!(
-            Err(ProgramError::MissingRequiredSignature),
-            do_process_instruction(
-                instruction,
-                vec![&mut mint_account, &mut owner2_account, &mut owner_account],
-            )
-        );
-
-        // set owner
-        do_process_instruction(
-            set_owner(&program_id, &mint_key, &owner2_key, &owner_key, &[]).unwrap(),
-            vec![&mut mint_account, &mut owner2_account, &mut owner_account],
-        )
-        .unwrap();
-
-        // create new mint without owner
-        do_process_instruction(
-            initialize_mint(&program_id, &mint2_key, Some(&account2_key), None, 1000, 2).unwrap(),
-            vec![&mut mint2_account, &mut account2_account],
-        )
-        .unwrap();
-
-        // set owner for non-mint-able token
-        assert_eq!(
-            Err(TokenError::OwnerMismatch.into()),
-            do_process_instruction(
-                set_owner(&program_id, &mint2_key, &owner2_key, &owner_key, &[]).unwrap(),
-                vec![&mut mint_account, &mut owner2_account, &mut owner_account],
-            )
-        );
-    }
-
-    #[test]
-    fn test_mint_to() {
-        let program_id = pubkey_rand();
-        let account_key = pubkey_rand();
-        let mut account_account = SolanaAccount::new(0, size_of::<Account>(), &program_id);
-        let account2_key = pubkey_rand();
-        let mut account2_account = SolanaAccount::new(0, size_of::<Account>(), &program_id);
-        let account3_key = pubkey_rand();
-        let mut account3_account = SolanaAccount::new(0, size_of::<Account>(), &program_id);
-        let mismatch_key = pubkey_rand();
-        let mut mismatch_account = SolanaAccount::new(0, size_of::<Account>(), &program_id);
-        let owner_key = pubkey_rand();
-        let mut owner_account = SolanaAccount::default();
-        let owner2_key = pubkey_rand();
-        let mut owner2_account = SolanaAccount::default();
-        let mint_key = pubkey_rand();
-        let mut mint_account = SolanaAccount::new(0, size_of::<Mint>(), &program_id);
-        let mint2_key = pubkey_rand();
-        let mut mint2_account = SolanaAccount::new(0, size_of::<Mint>(), &program_id);
-        let uninitialized_key = pubkey_rand();
-        let mut uninitialized_account = SolanaAccount::new(0, size_of::<Account>(), &program_id);
-
-        // create account
-        do_process_instruction(
-            initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
-            vec![&mut account_account, &mut mint_account, &mut owner_account],
-        )
-        .unwrap();
-
-        // create another account
-        do_process_instruction(
-            initialize_account(&program_id, &account2_key, &mint_key, &owner_key).unwrap(),
-            vec![&mut account2_account, &mut mint_account, &mut owner_account],
-        )
-        .unwrap();
-
-        // create another account
-        do_process_instruction(
-            initialize_account(&program_id, &account3_key, &mint_key, &owner_key).unwrap(),
-            vec![&mut account3_account, &mut mint_account, &mut owner_account],
-        )
-        .unwrap();
-
-        // create mismatch account
-        do_process_instruction(
-            initialize_account(&program_id, &mismatch_key, &mint2_key, &owner_key).unwrap(),
-            vec![
-                &mut mismatch_account,
-                &mut mint2_account,
-                &mut owner_account,
-            ],
-        )
-        .unwrap();
-
-        // create new mint with owner
-        do_process_instruction(
-            initialize_mint(
-                &program_id,
-                &mint_key,
-                Some(&account_key),
-                Some(&owner_key),
-                1000,
-                2,
-            )
-            .unwrap(),
-            vec![&mut mint_account, &mut account_account, &mut owner_account],
-        )
-        .unwrap();
-
-        // mint to
-        do_process_instruction(
-            mint_to(&program_id, &mint_key, &account2_key, &owner_key, &[], 42).unwrap(),
-            vec![&mut mint_account, &mut account2_account, &mut owner_account],
-        )
-        .unwrap();
-
-        let _: &mut Mint = state::unpack(&mut mint_account.data).unwrap();
-        let dest_account: &mut Account = state::unpack(&mut account2_account.data).unwrap();
-        assert_eq!(dest_account.amount, 42);
-
-        // missing signer
-        let mut instruction =
-            mint_to(&program_id, &mint_key, &account2_key, &owner_key, &[], 42).unwrap();
-        instruction.accounts[2].is_signer = false;
-        assert_eq!(
-            Err(ProgramError::MissingRequiredSignature),
-            do_process_instruction(
-                instruction,
-                vec![&mut mint_account, &mut account2_account, &mut owner_account],
-            )
-        );
-
-        // mismatch account
-        assert_eq!(
-            Err(TokenError::MintMismatch.into()),
-            do_process_instruction(
-                mint_to(&program_id, &mint_key, &mismatch_key, &owner_key, &[], 42).unwrap(),
-                vec![&mut mint_account, &mut mismatch_account, &mut owner_account],
-            )
-        );
-
-        // missing owner
-        assert_eq!(
-            Err(TokenError::OwnerMismatch.into()),
-            do_process_instruction(
-                mint_to(&program_id, &mint_key, &account2_key, &owner2_key, &[], 42).unwrap(),
-                vec![
-                    &mut mint_account,
-                    &mut account2_account,
-                    &mut owner2_account,
-                ],
-            )
-        );
-
-        // uninitialized destination account
-        assert_eq!(
-            Err(TokenError::UninitializedState.into()),
-            do_process_instruction(
-                mint_to(
-                    &program_id,
-                    &mint_key,
-                    &uninitialized_key,
-                    &owner_key,
-                    &[],
-                    42
-                )
-                .unwrap(),
-                vec![
-                    &mut mint_account,
-                    &mut uninitialized_account,
-                    &mut owner_account,
-                ],
-            )
-        );
-    }
-
-    #[test]
-    fn test_burn() {
-        let program_id = pubkey_rand();
-        let account_key = pubkey_rand();
-        let mut account_account = SolanaAccount::new(0, size_of::<Account>(), &program_id);
-        let account2_key = pubkey_rand();
-        let mut account2_account = SolanaAccount::new(0, size_of::<Account>(), &program_id);
-        let account3_key = pubkey_rand();
-        let mut account3_account = SolanaAccount::new(0, size_of::<Account>(), &program_id);
-        let delegate_key = pubkey_rand();
-        let mut delegate_account = SolanaAccount::default();
-        let mismatch_key = pubkey_rand();
-        let mut mismatch_account = SolanaAccount::new(0, size_of::<Account>(), &program_id);
-        let owner_key = pubkey_rand();
-        let mut owner_account = SolanaAccount::default();
-        let owner2_key = pubkey_rand();
-        let mut owner2_account = SolanaAccount::default();
-        let mint_key = pubkey_rand();
-        let mut mint_account = SolanaAccount::new(0, size_of::<Mint>(), &program_id);
-        let mint2_key = pubkey_rand();
-        let mut mint2_account = SolanaAccount::new(0, size_of::<Mint>(), &program_id);
-
-        // create account
-        do_process_instruction(
-            initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
-            vec![&mut account_account, &mut mint_account, &mut owner_account],
-        )
-        .unwrap();
-
-        // create another account
-        do_process_instruction(
-            initialize_account(&program_id, &account2_key, &mint_key, &owner_key).unwrap(),
-            vec![&mut account2_account, &mut mint_account, &mut owner_account],
-        )
-        .unwrap();
-
-        // create another account
-        do_process_instruction(
-            initialize_account(&program_id, &account3_key, &mint_key, &owner_key).unwrap(),
-            vec![&mut account3_account, &mut mint_account, &mut owner_account],
-        )
-        .unwrap();
-
-        // create mismatch account
-        do_process_instruction(
-            initialize_account(&program_id, &mismatch_key, &mint2_key, &owner_key).unwrap(),
-            vec![
-                &mut mismatch_account,
-                &mut mint2_account,
-                &mut owner_account,
-            ],
-        )
-        .unwrap();
-
-        // create new mint
-        do_process_instruction(
-            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, &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 delegate_account],
-            )
-        );
-
-        // missing owner
-        assert_eq!(
-            Err(TokenError::OwnerMismatch.into()),
-            do_process_instruction(
-                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, &owner_key, &[], 42).unwrap(),
-            vec![&mut account_account, &mut owner_account],
-        )
-        .unwrap();
-
-        let _: &mut Mint = state::unpack(&mut mint_account.data).unwrap();
-        let account: &mut Account = state::unpack(&mut account_account.data).unwrap();
-        assert_eq!(account.amount, 1000 - 42);
-
-        // insufficient funds
-        assert_eq!(
-            Err(TokenError::InsufficientFunds.into()),
-            do_process_instruction(
-                burn(&program_id, &account_key, &owner_key, &[], 100_000_000).unwrap(),
-                vec![&mut account_account, &mut owner_account],
-            )
-        );
-
-        // approve delegate
-        do_process_instruction(
-            approve(
-                &program_id,
-                &account_key,
-                &delegate_key,
-                &owner_key,
-                &[],
-                84,
-            )
-            .unwrap(),
-            vec![
-                &mut account_account,
-                &mut delegate_account,
-                &mut owner_account,
-            ],
-        )
-        .unwrap();
-
-        // not a delegate of source account
-        assert_eq!(
-            Err(TokenError::InsufficientFunds.into()),
-            do_process_instruction(
-                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, &delegate_key, &[], 84).unwrap(),
-            vec![&mut account_account, &mut delegate_account],
-        )
-        .unwrap();
-
-        // match
-        let _: &mut Mint = state::unpack(&mut mint_account.data).unwrap();
-        let account: &mut Account = state::unpack(&mut account_account.data).unwrap();
-        assert_eq!(account.amount, 1000 - 42 - 84);
-
-        // insufficient funds approved via delegate
-        assert_eq!(
-            Err(TokenError::OwnerMismatch.into()),
-            do_process_instruction(
-                burn(&program_id, &account_key, &delegate_key, &[], 100).unwrap(),
-                vec![&mut account_account, &mut delegate_account],
-            )
-        );
-    }
-
-    #[test]
-    fn test_multisig() {
-        let program_id = pubkey_rand();
-        let mint_key = pubkey_rand();
-        let mut mint_account = SolanaAccount::new(0, size_of::<Mint>(), &program_id);
-        let account_key = pubkey_rand();
-        let mut account = SolanaAccount::new(0, size_of::<Account>(), &program_id);
-        let account2_key = pubkey_rand();
-        let mut account2_account = SolanaAccount::new(0, size_of::<Account>(), &program_id);
-        let owner_key = pubkey_rand();
-        let mut owner_account = SolanaAccount::default();
-        let multisig_key = pubkey_rand();
-        let mut multisig_account = SolanaAccount::new(0, size_of::<Multisig>(), &program_id);
-        let multisig_delegate_key = pubkey_rand();
-        let mut multisig_delegate_account =
-            SolanaAccount::new(0, size_of::<Multisig>(), &program_id);
-        let signer_keys = vec![pubkey_rand(); MAX_SIGNERS];
-        let signer_key_refs: Vec<&Pubkey> = signer_keys.iter().map(|key| key).collect();
-        let mut signer_accounts = vec![SolanaAccount::new(0, 0, &program_id); MAX_SIGNERS];
-
-        // single signer
-        let account_info_iter = &mut signer_accounts.iter_mut();
-        do_process_instruction(
-            initialize_multisig(&program_id, &multisig_key, &[&signer_keys[0]], 1).unwrap(),
-            vec![
-                &mut multisig_account,
-                &mut account_info_iter.next().unwrap(),
-            ],
-        )
-        .unwrap();
-
-        // multiple signer
-        let account_info_iter = &mut signer_accounts.iter_mut();
-        do_process_instruction(
-            initialize_multisig(
-                &program_id,
-                &multisig_delegate_key,
-                &signer_key_refs,
-                MAX_SIGNERS as u8,
-            )
-            .unwrap(),
-            vec![
-                &mut multisig_delegate_account,
-                &mut account_info_iter.next().unwrap(),
-                &mut account_info_iter.next().unwrap(),
-                &mut account_info_iter.next().unwrap(),
-                &mut account_info_iter.next().unwrap(),
-                &mut account_info_iter.next().unwrap(),
-                &mut account_info_iter.next().unwrap(),
-                &mut account_info_iter.next().unwrap(),
-                &mut account_info_iter.next().unwrap(),
-                &mut account_info_iter.next().unwrap(),
-                &mut account_info_iter.next().unwrap(),
-                &mut account_info_iter.next().unwrap(),
-            ],
-        )
-        .unwrap();
-
-        // create account with multisig owner
-        do_process_instruction(
-            initialize_account(&program_id, &account_key, &mint_key, &multisig_key).unwrap(),
-            vec![&mut account, &mut mint_account, &mut multisig_account],
-        )
-        .unwrap();
-
-        // create another account with multisig owner
-        do_process_instruction(
-            initialize_account(
-                &program_id,
-                &account2_key,
-                &mint_key,
-                &multisig_delegate_key,
-            )
-            .unwrap(),
-            vec![
-                &mut account2_account,
-                &mut mint_account,
-                &mut multisig_account,
-            ],
-        )
-        .unwrap();
-
-        // create new m int with multisig owner
-        do_process_instruction(
-            initialize_mint(
-                &program_id,
-                &mint_key,
-                Some(&account_key),
-                Some(&multisig_key),
-                1000,
-                2,
-            )
-            .unwrap(),
-            vec![&mut mint_account, &mut account, &mut multisig_account],
-        )
-        .unwrap();
-
-        // approve
-        let account_info_iter = &mut signer_accounts.iter_mut();
-        do_process_instruction(
-            approve(
-                &program_id,
-                &account_key,
-                &multisig_delegate_key,
-                &multisig_key,
-                &[&signer_keys[0]],
-                100,
-            )
-            .unwrap(),
-            vec![
-                &mut account,
-                &mut multisig_delegate_account,
-                &mut multisig_account,
-                &mut account_info_iter.next().unwrap(),
-            ],
-        )
-        .unwrap();
-
-        // transfer
-        let account_info_iter = &mut signer_accounts.iter_mut();
-        do_process_instruction(
-            transfer(
-                &program_id,
-                &account_key,
-                &account2_key,
-                &multisig_key,
-                &[&signer_keys[0]],
-                42,
-            )
-            .unwrap(),
-            vec![
-                &mut account,
-                &mut account2_account,
-                &mut multisig_account,
-                &mut account_info_iter.next().unwrap(),
-            ],
-        )
-        .unwrap();
-
-        // transfer via delegate
-        let account_info_iter = &mut signer_accounts.iter_mut();
-        do_process_instruction(
-            transfer(
-                &program_id,
-                &account_key,
-                &account2_key,
-                &multisig_delegate_key,
-                &signer_key_refs,
-                42,
-            )
-            .unwrap(),
-            vec![
-                &mut account,
-                &mut account2_account,
-                &mut multisig_delegate_account,
-                &mut account_info_iter.next().unwrap(),
-                &mut account_info_iter.next().unwrap(),
-                &mut account_info_iter.next().unwrap(),
-                &mut account_info_iter.next().unwrap(),
-                &mut account_info_iter.next().unwrap(),
-                &mut account_info_iter.next().unwrap(),
-                &mut account_info_iter.next().unwrap(),
-                &mut account_info_iter.next().unwrap(),
-                &mut account_info_iter.next().unwrap(),
-                &mut account_info_iter.next().unwrap(),
-                &mut account_info_iter.next().unwrap(),
-            ],
-        )
-        .unwrap();
-
-        // mint to
-        let account_info_iter = &mut signer_accounts.iter_mut();
-        do_process_instruction(
-            mint_to(
-                &program_id,
-                &mint_key,
-                &account2_key,
-                &multisig_key,
-                &[&signer_keys[0]],
-                42,
-            )
-            .unwrap(),
-            vec![
-                &mut mint_account,
-                &mut account2_account,
-                &mut multisig_account,
-                &mut account_info_iter.next().unwrap(),
-            ],
-        )
-        .unwrap();
-
-        // burn
-        let account_info_iter = &mut signer_accounts.iter_mut();
-        do_process_instruction(
-            burn(
-                &program_id,
-                &account_key,
-                &multisig_key,
-                &[&signer_keys[0]],
-                42,
-            )
-            .unwrap(),
-            vec![
-                &mut account,
-                &mut multisig_account,
-                &mut account_info_iter.next().unwrap(),
-            ],
-        )
-        .unwrap();
-
-        // burn via delegate
-        let account_info_iter = &mut signer_accounts.iter_mut();
-        do_process_instruction(
-            burn(
-                &program_id,
-                &account_key,
-                &multisig_delegate_key,
-                &signer_key_refs,
-                42,
-            )
-            .unwrap(),
-            vec![
-                &mut account,
-                &mut multisig_delegate_account,
-                &mut account_info_iter.next().unwrap(),
-                &mut account_info_iter.next().unwrap(),
-                &mut account_info_iter.next().unwrap(),
-                &mut account_info_iter.next().unwrap(),
-                &mut account_info_iter.next().unwrap(),
-                &mut account_info_iter.next().unwrap(),
-                &mut account_info_iter.next().unwrap(),
-                &mut account_info_iter.next().unwrap(),
-                &mut account_info_iter.next().unwrap(),
-                &mut account_info_iter.next().unwrap(),
-                &mut account_info_iter.next().unwrap(),
-            ],
-        )
-        .unwrap();
-
-        // do SetOwner on mint
-        let account_info_iter = &mut signer_accounts.iter_mut();
-        do_process_instruction(
-            set_owner(
-                &program_id,
-                &mint_key,
-                &owner_key,
-                &multisig_key,
-                &[&signer_keys[0]],
-            )
-            .unwrap(),
-            vec![
-                &mut mint_account,
-                &mut owner_account,
-                &mut multisig_account,
-                &mut account_info_iter.next().unwrap(),
-            ],
-        )
-        .unwrap();
-
-        // do SetOwner on account
-        let account_info_iter = &mut signer_accounts.iter_mut();
-        do_process_instruction(
-            set_owner(
-                &program_id,
-                &account_key,
-                &owner_key,
-                &multisig_key,
-                &[&signer_keys[0]],
-            )
-            .unwrap(),
-            vec![
-                &mut account,
-                &mut owner_account,
-                &mut multisig_account,
-                &mut account_info_iter.next().unwrap(),
-            ],
-        )
-        .unwrap();
-    }
-
-    #[test]
-    fn test_validate_owner() {
-        let program_id = pubkey_rand();
-        let owner_key = pubkey_rand();
-        let mut signer_keys = [Pubkey::default(); MAX_SIGNERS];
-        for signer_key in signer_keys.iter_mut().take(MAX_SIGNERS) {
-            *signer_key = pubkey_rand();
-        }
-        let mut signer_lamports = 0;
-        let mut signer_data = vec![];
-        let mut signers = vec![
-            AccountInfo::new(
-                &owner_key,
-                true,
-                false,
-                &mut signer_lamports,
-                &mut signer_data,
-                &program_id,
-                false,
-                Epoch::default(),
-            );
-            MAX_SIGNERS + 1
-        ];
-        for (signer, key) in signers.iter_mut().zip(&signer_keys) {
-            signer.key = key;
-        }
-        let mut lamports = 0;
-        let mut data = vec![0; size_of::<Multisig>()];
-        let mut multisig: &mut Multisig = state::unpack_unchecked(&mut data).unwrap();
-        multisig.m = MAX_SIGNERS as u8;
-        multisig.n = MAX_SIGNERS as u8;
-        multisig.signers = signer_keys;
-        multisig.is_initialized = true;
-        let owner_account_info = AccountInfo::new(
-            &owner_key,
-            false,
-            false,
-            &mut lamports,
-            &mut data,
-            &program_id,
-            false,
-            Epoch::default(),
-        );
-
-        // full 11 of 11
-        Processor::validate_owner(&program_id, &owner_key, &owner_account_info, &signers).unwrap();
-
-        // 1 of 11
-        {
-            let mut data_ref_mut = owner_account_info.data.borrow_mut();
-            let mut multisig: &mut Multisig = state::unpack(&mut data_ref_mut).unwrap();
-            multisig.m = 1;
-        }
-        Processor::validate_owner(&program_id, &owner_key, &owner_account_info, &signers).unwrap();
-
-        // 2:1
-        {
-            let mut data_ref_mut = owner_account_info.data.borrow_mut();
-            let mut multisig: &mut Multisig = state::unpack(&mut data_ref_mut).unwrap();
-            multisig.m = 2;
-            multisig.n = 1;
-        }
-        assert_eq!(
-            Err(ProgramError::MissingRequiredSignature),
-            Processor::validate_owner(&program_id, &owner_key, &owner_account_info, &signers)
-        );
-
-        // 0:11
-        {
-            let mut data_ref_mut = owner_account_info.data.borrow_mut();
-            let mut multisig: &mut Multisig = state::unpack(&mut data_ref_mut).unwrap();
-            multisig.m = 0;
-            multisig.n = 11;
-        }
-        Processor::validate_owner(&program_id, &owner_key, &owner_account_info, &signers).unwrap();
-
-        // 2:11 but 0 provided
-        {
-            let mut data_ref_mut = owner_account_info.data.borrow_mut();
-            let mut multisig: &mut Multisig = state::unpack(&mut data_ref_mut).unwrap();
-            multisig.m = 2;
-            multisig.n = 11;
-        }
-        assert_eq!(
-            Err(ProgramError::MissingRequiredSignature),
-            Processor::validate_owner(&program_id, &owner_key, &owner_account_info, &[])
-        );
-        // 2:11 but 1 provided
-        {
-            let mut data_ref_mut = owner_account_info.data.borrow_mut();
-            let mut multisig: &mut Multisig = state::unpack(&mut data_ref_mut).unwrap();
-            multisig.m = 2;
-            multisig.n = 11;
-        }
-        assert_eq!(
-            Err(ProgramError::MissingRequiredSignature),
-            Processor::validate_owner(&program_id, &owner_key, &owner_account_info, &signers[0..1])
-        );
-
-        // 2:11, 2 from middle provided
-        {
-            let mut data_ref_mut = owner_account_info.data.borrow_mut();
-            let mut multisig: &mut Multisig = state::unpack(&mut data_ref_mut).unwrap();
-            multisig.m = 2;
-            multisig.n = 11;
-        }
-        Processor::validate_owner(&program_id, &owner_key, &owner_account_info, &signers[5..7])
-            .unwrap();
-
-        // 11:11, one is not a signer
-        {
-            let mut data_ref_mut = owner_account_info.data.borrow_mut();
-            let mut multisig: &mut Multisig = state::unpack(&mut data_ref_mut).unwrap();
-            multisig.m = 2;
-            multisig.n = 11;
-        }
-        signers[5].is_signer = false;
-        assert_eq!(
-            Err(ProgramError::MissingRequiredSignature),
-            Processor::validate_owner(&program_id, &owner_key, &owner_account_info, &signers)
-        );
-        signers[5].is_signer = true;
-    }
-
-    #[test]
-    fn test_close_account() {
-        let program_id = pubkey_rand();
-        let mint_key = pubkey_rand();
-        let mut mint_account = SolanaAccount::new(0, size_of::<Mint>(), &program_id);
-        let account_key = pubkey_rand();
-        let mut account_account = SolanaAccount::new(42, size_of::<Account>(), &program_id);
-        let account2_key = pubkey_rand();
-        let mut account2_account = SolanaAccount::new(2, size_of::<Account>(), &program_id);
-        let account3_key = pubkey_rand();
-        let mut account3_account = SolanaAccount::new(2, size_of::<Account>(), &program_id);
-        let owner_key = pubkey_rand();
-        let mut owner_account = SolanaAccount::default();
-        let owner2_key = pubkey_rand();
-        let mut owner2_account = SolanaAccount::default();
-
-        // uninitialized
-        assert_eq!(
-            Err(TokenError::UninitializedState.into()),
-            do_process_instruction(
-                close_account(&program_id, &account_key, &account3_key, &owner2_key, &[]).unwrap(),
-                vec![
-                    &mut account_account,
-                    &mut account3_account,
-                    &mut owner2_account,
-                ],
-            )
-        );
-
-        // initialize non-native account
-        do_process_instruction(
-            initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
-            vec![&mut account_account, &mut mint_account, &mut owner_account],
-        )
-        .unwrap();
-
-        // initialize native account
-        do_process_instruction(
-            initialize_account(
-                &program_id,
-                &account2_key,
-                &crate::native_mint::id(),
-                &owner_key,
-            )
-            .unwrap(),
-            vec![&mut account2_account, &mut mint_account, &mut owner_account],
-        )
-        .unwrap();
-        let account: &mut Account = state::unpack(&mut account2_account.data).unwrap();
-        assert!(account.is_native);
-        assert_eq!(account.amount, 2);
-
-        // close non-native account
-        assert_eq!(
-            Err(TokenError::NonNativeNotSupported.into()),
-            do_process_instruction(
-                close_account(&program_id, &account_key, &account3_key, &owner_key, &[]).unwrap(),
-                vec![
-                    &mut account_account,
-                    &mut account3_account,
-                    &mut owner_account,
-                ],
-            )
-        );
-        assert_eq!(account_account.lamports, 42);
-
-        // close native account
-        do_process_instruction(
-            close_account(&program_id, &account2_key, &account3_key, &owner_key, &[]).unwrap(),
-            vec![
-                &mut account2_account,
-                &mut account3_account,
-                &mut owner_account,
-            ],
-        )
-        .unwrap();
-        let account: &mut Account = state::unpack_unchecked(&mut account2_account.data).unwrap();
-        assert!(account.is_native);
-        assert_eq!(account.amount, 0);
-        assert_eq!(account3_account.lamports, 4);
-    }
-
-    #[test]
-    fn test_native_token() {
-        let program_id = pubkey_rand();
-        let mut mint_account = SolanaAccount::new(0, size_of::<Mint>(), &program_id);
-        let account_key = pubkey_rand();
-        let mut account_account = SolanaAccount::new(42, size_of::<Account>(), &program_id);
-        let account2_key = pubkey_rand();
-        let mut account2_account = SolanaAccount::new(2, size_of::<Account>(), &program_id);
-        let account3_key = pubkey_rand();
-        let mut account3_account = SolanaAccount::new(2, 0, &program_id);
-        let owner_key = pubkey_rand();
-        let mut owner_account = SolanaAccount::default();
-
-        // initialize native account
-        do_process_instruction(
-            initialize_account(
-                &program_id,
-                &account_key,
-                &crate::native_mint::id(),
-                &owner_key,
-            )
-            .unwrap(),
-            vec![&mut account_account, &mut mint_account, &mut owner_account],
-        )
-        .unwrap();
-        let account: &mut Account = state::unpack(&mut account_account.data).unwrap();
-        assert!(account.is_native);
-        assert_eq!(account.amount, 42);
-
-        // initialize native account
-        do_process_instruction(
-            initialize_account(
-                &program_id,
-                &account2_key,
-                &crate::native_mint::id(),
-                &owner_key,
-            )
-            .unwrap(),
-            vec![&mut account2_account, &mut mint_account, &mut owner_account],
-        )
-        .unwrap();
-        let account: &mut Account = state::unpack(&mut account2_account.data).unwrap();
-        assert!(account.is_native);
-        assert_eq!(account.amount, 2);
-
-        // mint_to unsupported
-        assert_eq!(
-            Err(TokenError::NativeNotSupported.into()),
-            do_process_instruction(
-                mint_to(
-                    &program_id,
-                    &crate::native_mint::id(),
-                    &account_key,
-                    &owner_key,
-                    &[],
-                    42
-                )
-                .unwrap(),
-                vec![&mut mint_account, &mut account_account, &mut owner_account],
-            )
-        );
-
-        // burn unsupported
-        assert_eq!(
-            Err(TokenError::NativeNotSupported.into()),
-            do_process_instruction(
-                burn(&program_id, &account_key, &owner_key, &[], 42).unwrap(),
-                vec![&mut account_account, &mut owner_account],
-            )
-        );
-
-        // initialize native account
-        do_process_instruction(
-            transfer(
-                &program_id,
-                &account_key,
-                &account2_key,
-                &owner_key,
-                &[],
-                40,
-            )
-            .unwrap(),
-            vec![
-                &mut account_account,
-                &mut account2_account,
-                &mut owner_account,
-            ],
-        )
-        .unwrap();
-
-        let account: &mut Account = state::unpack(&mut account_account.data).unwrap();
-        assert!(account.is_native);
-        assert_eq!(account_account.lamports, 2);
-        assert_eq!(account.amount, 2);
-        let account: &mut Account = state::unpack(&mut account2_account.data).unwrap();
-        assert!(account.is_native);
-        assert_eq!(account2_account.lamports, 42);
-        assert_eq!(account.amount, 42);
-
-        // close native account
-        do_process_instruction(
-            close_account(&program_id, &account_key, &account3_key, &owner_key, &[]).unwrap(),
-            vec![
-                &mut account_account,
-                &mut account3_account,
-                &mut owner_account,
-            ],
-        )
-        .unwrap();
-        let account: &mut Account = state::unpack_unchecked(&mut account_account.data).unwrap();
-        assert!(account.is_native);
-        assert_eq!(account_account.lamports, 0);
-        assert_eq!(account.amount, 0);
-        assert_eq!(account3_account.lamports, 4);
-    }
-
-    #[test]
-    fn test_overflow() {
-        let program_id = pubkey_rand();
-        let account_key = pubkey_rand();
-        let mut account_account = SolanaAccount::new(0, size_of::<Account>(), &program_id);
-        let account2_key = pubkey_rand();
-        let mut account2_account = SolanaAccount::new(0, size_of::<Account>(), &program_id);
-        let owner_key = pubkey_rand();
-        let mut owner_account = SolanaAccount::default();
-        let owner2_key = pubkey_rand();
-        let mut owner2_account = SolanaAccount::default();
-        let mint_owner_key = pubkey_rand();
-        let mut mint_owner_account = SolanaAccount::default();
-        let mint_key = pubkey_rand();
-        let mut mint_account = SolanaAccount::new(0, size_of::<Mint>(), &program_id);
-
-        // create victim account
-        do_process_instruction(
-            initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
-            vec![&mut account_account, &mut mint_account, &mut owner_account],
-        )
-        .unwrap();
-
-        // create another account
-        do_process_instruction(
-            initialize_account(&program_id, &account2_key, &mint_key, &owner2_key).unwrap(),
-            vec![
-                &mut account2_account,
-                &mut mint_account,
-                &mut owner2_account,
-            ],
-        )
-        .unwrap();
-
-        // create new mint with owner
-        do_process_instruction(
-            initialize_mint(&program_id, &mint_key, None, Some(&mint_owner_key), 0, 2).unwrap(),
-            vec![&mut mint_account, &mut mint_owner_account],
-        )
-        .unwrap();
-
-        // mint the max to attacker
-        do_process_instruction(
-            mint_to(
-                &program_id,
-                &mint_key,
-                &account2_key,
-                &mint_owner_key,
-                &[],
-                42,
-            )
-            .unwrap(),
-            vec![
-                &mut mint_account,
-                &mut account2_account,
-                &mut mint_owner_account,
-            ],
-        )
-        .unwrap();
-        let account: &mut Account = state::unpack(&mut account2_account.data).unwrap();
-        assert_eq!(account.amount, 42);
-
-        // mint the max to victum
-        do_process_instruction(
-            mint_to(
-                &program_id,
-                &mint_key,
-                &account_key,
-                &mint_owner_key,
-                &[],
-                u64::MAX,
-            )
-            .unwrap(),
-            vec![
-                &mut mint_account,
-                &mut account_account,
-                &mut mint_owner_account,
-            ],
-        )
-        .unwrap();
-        let account: &mut Account = state::unpack(&mut account_account.data).unwrap();
-        assert_eq!(account.amount, u64::MAX);
-
-        // mint one more
-        assert_eq!(
-            Err(TokenError::Overflow.into()),
-            do_process_instruction(
-                mint_to(
-                    &program_id,
-                    &mint_key,
-                    &account_key,
-                    &mint_owner_key,
-                    &[],
-                    1,
-                )
-                .unwrap(),
-                vec![
-                    &mut mint_account,
-                    &mut account_account,
-                    &mut mint_owner_account,
-                ],
-            )
-        );
-
-        // mint back to large amount
-        let account: &mut Account = state::unpack(&mut account_account.data).unwrap();
-        account.amount = 0;
-        do_process_instruction(
-            mint_to(
-                &program_id,
-                &mint_key,
-                &account_key,
-                &mint_owner_key,
-                &[],
-                u64::MAX,
-            )
-            .unwrap(),
-            vec![
-                &mut mint_account,
-                &mut account_account,
-                &mut mint_owner_account,
-            ],
-        )
-        .unwrap();
-        let account: &mut Account = state::unpack(&mut account_account.data).unwrap();
-        assert_eq!(account.amount, u64::MAX);
-
-        // transfer to burn victim
-        assert_eq!(
-            Err(TokenError::Overflow.into()),
-            do_process_instruction(
-                transfer(
-                    &program_id,
-                    &account2_key,
-                    &account_key,
-                    &owner2_key,
-                    &[],
-                    1,
-                )
-                .unwrap(),
-                vec![
-                    &mut account2_account,
-                    &mut account_account,
-                    &mut owner2_account,
-                ],
-            )
-        );
-    }
-}

+ 0 - 92
program/src/state.rs

@@ -1,92 +0,0 @@
-//! State transition types
-
-use crate::{error::TokenError, instruction::MAX_SIGNERS, option::COption};
-use solana_sdk::{program_error::ProgramError, pubkey::Pubkey};
-use std::mem::size_of;
-
-/// Mint data.
-#[repr(C)]
-#[derive(Clone, Copy, Debug, Default, PartialEq)]
-pub struct Mint {
-    /// 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,
-    /// Is `true` if this structure has been initialized
-    pub is_initialized: bool,
-}
-impl IsInitialized for Mint {
-    fn is_initialized(&self) -> bool {
-        self.is_initialized
-    }
-}
-
-/// Account data.
-#[repr(C)]
-#[derive(Clone, Copy, Debug, Default, PartialEq)]
-pub struct Account {
-    /// The mint associated with this account
-    pub mint: Pubkey,
-    /// The owner of this account.
-    pub owner: Pubkey,
-    /// The amount of tokens this account holds.
-    pub amount: u64,
-    /// If `delegate` is `Some` then `delegated_amount` represents
-    /// the amount authorized by the delegate
-    pub delegate: COption<Pubkey>,
-    /// Is `true` if this structure has been initialized
-    pub is_initialized: bool,
-    /// Is this a native token
-    pub is_native: bool,
-    /// The amount delegated
-    pub delegated_amount: u64,
-}
-impl IsInitialized for Account {
-    fn is_initialized(&self) -> bool {
-        self.is_initialized
-    }
-}
-
-/// Multisignature data.
-#[repr(C)]
-#[derive(Clone, Copy, Debug, Default, PartialEq)]
-pub struct Multisig {
-    /// Number of signers required
-    pub m: u8,
-    /// Number of valid signers
-    pub n: u8,
-    /// Is `true` if this structure has been initialized
-    pub is_initialized: bool,
-    /// Signer public keys
-    pub signers: [Pubkey; MAX_SIGNERS],
-}
-impl IsInitialized for Multisig {
-    fn is_initialized(&self) -> bool {
-        self.is_initialized
-    }
-}
-
-/// Check is a token state is initialized
-pub trait IsInitialized {
-    /// Is initialized
-    fn is_initialized(&self) -> bool;
-}
-
-/// Unpacks a token state from a bytes buffer while assuring that the state is initialized.
-pub fn unpack<T: IsInitialized>(input: &mut [u8]) -> Result<&mut T, ProgramError> {
-    let mut_ref: &mut T = unpack_unchecked(input)?;
-    if !mut_ref.is_initialized() {
-        return Err(TokenError::UninitializedState.into());
-    }
-    Ok(mut_ref)
-}
-/// Unpacks a token state from a bytes buffer without checking that the state is initialized.
-pub fn unpack_unchecked<T: IsInitialized>(input: &mut [u8]) -> Result<&mut T, ProgramError> {
-    if input.len() != size_of::<T>() {
-        return Err(ProgramError::InvalidAccountData);
-    }
-    #[allow(clippy::cast_ptr_alignment)]
-    Ok(unsafe { &mut *(&mut input[0] as *mut u8 as *mut T) })
-}