|
@@ -331,9 +331,21 @@ pub trait GenericTokenAccount {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+/// The offset of state field in Account's C representation
|
|
|
+pub const ACCOUNT_INITIALIZED_INDEX: usize = 108;
|
|
|
+
|
|
|
+/// Check if the account data buffer represents an initialized account.
|
|
|
+/// This is checking the `state` (AccountState) field of an Account object.
|
|
|
+pub fn is_initialized_account(account_data: &[u8]) -> bool {
|
|
|
+ *account_data
|
|
|
+ .get(ACCOUNT_INITIALIZED_INDEX)
|
|
|
+ .unwrap_or(&(AccountState::Uninitialized as u8))
|
|
|
+ != AccountState::Uninitialized as u8
|
|
|
+}
|
|
|
+
|
|
|
impl GenericTokenAccount for Account {
|
|
|
fn valid_account_data(account_data: &[u8]) -> bool {
|
|
|
- account_data.len() == Account::LEN
|
|
|
+ account_data.len() == Account::LEN && is_initialized_account(account_data)
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -418,11 +430,22 @@ mod tests {
|
|
|
let result = Account::unpack_account_owner(&src);
|
|
|
assert_eq!(result, Option::None);
|
|
|
|
|
|
- // The right account data size, unpack will return some key
|
|
|
- let src: [u8; Account::LEN] = [0; Account::LEN];
|
|
|
+ // The right account data size and intialized, unpack will return some key
|
|
|
+ let mut src: [u8; Account::LEN] = [0; Account::LEN];
|
|
|
+ src[ACCOUNT_INITIALIZED_INDEX] = AccountState::Initialized as u8;
|
|
|
let result = Account::unpack_account_owner(&src);
|
|
|
assert!(result.is_some());
|
|
|
|
|
|
+ // The right account data size and frozen, unpack will return some key
|
|
|
+ src[ACCOUNT_INITIALIZED_INDEX] = AccountState::Frozen as u8;
|
|
|
+ let result = Account::unpack_account_owner(&src);
|
|
|
+ assert!(result.is_some());
|
|
|
+
|
|
|
+ // The right account data size and uninitialized, unpack will return None
|
|
|
+ src[ACCOUNT_INITIALIZED_INDEX] = AccountState::Uninitialized as u8;
|
|
|
+ let result = Account::unpack_account_mint(&src);
|
|
|
+ assert_eq!(result, Option::None);
|
|
|
+
|
|
|
// Account data length > account data size, unpack will not return a key
|
|
|
let src: [u8; Account::LEN + 5] = [0; Account::LEN + 5];
|
|
|
let result = Account::unpack_account_owner(&src);
|
|
@@ -436,11 +459,22 @@ mod tests {
|
|
|
let result = Account::unpack_account_mint(&src);
|
|
|
assert_eq!(result, Option::None);
|
|
|
|
|
|
- // The right account data size, unpack will return some key
|
|
|
- let src: [u8; Account::LEN] = [0; Account::LEN];
|
|
|
+ // The right account data size and initialized, unpack will return some key
|
|
|
+ let mut src: [u8; Account::LEN] = [0; Account::LEN];
|
|
|
+ src[ACCOUNT_INITIALIZED_INDEX] = AccountState::Initialized as u8;
|
|
|
+ let result = Account::unpack_account_mint(&src);
|
|
|
+ assert!(result.is_some());
|
|
|
+
|
|
|
+ // The right account data size and frozen, unpack will return some key
|
|
|
+ src[ACCOUNT_INITIALIZED_INDEX] = AccountState::Frozen as u8;
|
|
|
let result = Account::unpack_account_mint(&src);
|
|
|
assert!(result.is_some());
|
|
|
|
|
|
+ // The right account data size and uninitialized, unpack will return None
|
|
|
+ src[ACCOUNT_INITIALIZED_INDEX] = AccountState::Uninitialized as u8;
|
|
|
+ let result = Account::unpack_account_mint(&src);
|
|
|
+ assert_eq!(result, Option::None);
|
|
|
+
|
|
|
// Account data length > account data size, unpack will not return a key
|
|
|
let src: [u8; Account::LEN + 5] = [0; Account::LEN + 5];
|
|
|
let result = Account::unpack_account_mint(&src);
|