diff --git a/program/src/processor/close.rs b/program/src/processor/close.rs
index ad6a8fe..d879e39 100644
--- a/program/src/processor/close.rs
+++ b/program/src/processor/close.rs
@@ -2,7 +2,7 @@ use pinocchio::{account_info::AccountInfo, program_error::ProgramError, ProgramR
 
 use crate::state::AccountDiscriminator;
 
-use super::validate_authority;
+use super::{validate_authority, validate_metadata};
 
 /// Closes a program-owned account.
 ///
@@ -34,8 +34,8 @@ pub fn close(accounts: &[AccountInfo]) -> ProgramResult {
             }
         }
         AccountDiscriminator::Metadata => {
-            // Metadata and authority validation is done in the `validate_authority`.
-            validate_authority(account, authority, program, program_data)?
+            let header = validate_metadata(account)?;
+            validate_authority(header, authority, program, program_data)?
         }
         _ => return Err(ProgramError::InvalidAccountData),
     }
diff --git a/program/src/processor/mod.rs b/program/src/processor/mod.rs
index 6cdd771..e01b4aa 100644
--- a/program/src/processor/mod.rs
+++ b/program/src/processor/mod.rs
@@ -82,24 +82,15 @@ fn is_program_authority(
     Ok(is_program_authority)
 }
 
-/// Ensures the `metadata` account can be updated by the provided `authority`.
+/// Ensures the `metadata` account is valid and mutable.
 ///
 /// ## Validation
 /// The following validation checks are performed:
 ///
 /// - [explicit] The `metadata` account discriminator (first byte) must be `2` — i.e. defining a `Metadata` account.
 /// - [explicit] The `metadata` account must be mutable — i.e. `mutable = true`.
-/// - [explicit] The `authority` account must be a signer.
-/// - [explicit] The `authority` account must match the authority set on the `metadata` account OR
-///   it must be the program upgrade authority if the `metadata` account is canonical (see `is_program_authority`).
 #[inline(always)]
-fn validate_authority(
-    metadata: &AccountInfo,
-    authority: &AccountInfo,
-    program: &AccountInfo,
-    program_data: &AccountInfo,
-) -> Result<(), ProgramError> {
-    // Metadata checks.
+fn validate_metadata(metadata: &AccountInfo) -> Result<&Header, ProgramError> {
     let header = unsafe { Header::load_unchecked(metadata.borrow_data_unchecked()) };
     if header.discriminator != AccountDiscriminator::Metadata as u8 {
         return Err(ProgramError::UninitializedAccount);
@@ -108,20 +99,37 @@ fn validate_authority(
         // TODO: use custom error (immutable metadata account)
         return Err(ProgramError::InvalidAccountData);
     }
+    Ok(header)
+}
 
+/// Ensures the `metadata` account can be updated by the provided `authority`.
+///
+/// ## Validation
+/// The following validation checks are performed:
+///
+/// - [explicit] The `authority` account must be a signer.
+/// - [explicit] The `authority` account must match the authority set on the `metadata` account OR
+///   it must be the program upgrade authority if the `metadata` account is canonical (see `is_program_authority`).
+#[inline(always)]
+fn validate_authority(
+    metadata_header: &Header,
+    authority: &AccountInfo,
+    program: &AccountInfo,
+    program_data: &AccountInfo,
+) -> Result<(), ProgramError> {
     // Authority checks.
     if !authority.is_signer() {
         return Err(ProgramError::MissingRequiredSignature);
     }
     // The authority is the set authority.
-    let explicitly_authorized = match header.authority.as_ref() {
+    let explicitly_authorized = match metadata_header.authority.as_ref() {
         Some(metadata_authority) => metadata_authority == authority.key(),
         None => false,
     };
     // The authority is the program upgrade authority for canonical metadata accounts.
     let authorized = explicitly_authorized
-        || (header.canonical()
-            && program.key() == &header.program
+        || (metadata_header.canonical()
+            && program.key() == &metadata_header.program
             && is_program_authority(program, program_data, authority.key())?);
     if !authorized {
         return Err(ProgramError::IncorrectAuthority);
diff --git a/program/src/processor/set_authority.rs b/program/src/processor/set_authority.rs
index 9040426..0f656b3 100644
--- a/program/src/processor/set_authority.rs
+++ b/program/src/processor/set_authority.rs
@@ -4,7 +4,7 @@ use pinocchio::{
 
 use crate::state::{header::Header, Zeroable};
 
-use super::validate_authority;
+use super::{validate_authority, validate_metadata};
 
 /// Sets the authority of a metadata account.
 ///
@@ -24,7 +24,8 @@ pub fn set_authority(accounts: &[AccountInfo], instruction_data: &[u8]) -> Progr
     // Accounts validation is done in the `validate_authority` function.
     //  - metadata: program owned is implicitly checked since we are writing to
     //    the account
-    validate_authority(metadata, authority, program, program_data)?;
+    let header = validate_metadata(metadata)?;
+    validate_authority(header, authority, program, program_data)?;
 
     let header = unsafe { Header::load_mut_unchecked(metadata.borrow_mut_data_unchecked()) };
 
diff --git a/program/src/processor/set_data.rs b/program/src/processor/set_data.rs
index f070b08..1466778 100644
--- a/program/src/processor/set_data.rs
+++ b/program/src/processor/set_data.rs
@@ -6,7 +6,7 @@ use crate::state::{
     header::Header, AccountDiscriminator, Compression, DataSource, Encoding, Format,
 };
 
-use super::validate_authority;
+use super::{validate_authority, validate_metadata};
 
 /// Update the data of a metadata account.
 pub fn set_data(accounts: &[AccountInfo], instruction_data: &[u8]) -> ProgramResult {
@@ -24,7 +24,8 @@ pub fn set_data(accounts: &[AccountInfo], instruction_data: &[u8]) -> ProgramRes
     };
 
     // Validate authority.
-    validate_authority(metadata, authority, program, program_data)?;
+    let header = validate_metadata(metadata)?;
+    validate_authority(header, authority, program, program_data)?;
 
     // Validate metadata account.
     let metadata_account_data = unsafe { metadata.borrow_mut_data_unchecked() };
diff --git a/program/src/processor/set_immutable.rs b/program/src/processor/set_immutable.rs
index 93f0b2b..d0c4931 100644
--- a/program/src/processor/set_immutable.rs
+++ b/program/src/processor/set_immutable.rs
@@ -2,7 +2,7 @@ use pinocchio::{account_info::AccountInfo, program_error::ProgramError, ProgramR
 
 use crate::state::header::Header;
 
-use super::validate_authority;
+use super::{validate_authority, validate_metadata};
 
 /// Sets the metadata account as immutable.
 ///
@@ -16,7 +16,8 @@ pub fn set_immutable(accounts: &[AccountInfo]) -> ProgramResult {
     };
 
     // Accounts validation is done in the `validate_authority` function.
-    validate_authority(metadata, authority, program, program_data)?;
+    let header = validate_metadata(metadata)?;
+    validate_authority(header, authority, program, program_data)?;
 
     // Make the metadata account immutable.
 
diff --git a/program/src/processor/withdraw_excess_lamports.rs b/program/src/processor/withdraw_excess_lamports.rs
index 44979e0..4605afe 100644
--- a/program/src/processor/withdraw_excess_lamports.rs
+++ b/program/src/processor/withdraw_excess_lamports.rs
@@ -2,7 +2,7 @@ use pinocchio::{
     account_info::AccountInfo, program_error::ProgramError, sysvars::rent::Rent, ProgramResult,
 };
 
-use super::validate_authority;
+use super::{validate_authority, validate_metadata};
 
 /// Withdraws excess lamports from a metadata account.
 ///
@@ -16,7 +16,8 @@ pub fn withdraw_excess_lamports(accounts: &[AccountInfo]) -> ProgramResult {
     };
 
     // Accounts validation is done in the `validate_authority` function.
-    validate_authority(metadata, authority, program, program_data)?;
+    let header = validate_metadata(metadata)?;
+    validate_authority(header, authority, program, program_data)?;
 
     // Withdraw the excess lamports in the account.