Browse Source

p-token: Add error logging (#41)

* Add fixtures test script

* Add error logging

* Update pinocchio dependencies

* Fix formatting
Fernando Otero 6 months ago
parent
commit
4c467485a4
7 changed files with 105 additions and 35 deletions
  1. 9 19
      Cargo.lock
  2. 2 2
      interface/Cargo.toml
  3. 70 1
      interface/src/error.rs
  4. 2 2
      p-token/Cargo.toml
  5. 18 6
      p-token/src/entrypoint.rs
  6. 4 4
      p-token/src/processor/mod.rs
  7. 0 1
      package.json

+ 9 - 19
Cargo.lock

@@ -2805,31 +2805,21 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
 
 [[package]]
 name = "pinocchio"
-version = "0.7.1"
-source = "git+https://github.com/febo/pinocchio.git?branch=febo%2Fclose-unstable#246a026bb74c501ba83ea18201000e56c097cb0d"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2281a8e9e947c480ce0b64e2d6c6349d72890ba5db6503d5568edf96f304cba9"
 
 [[package]]
 name = "pinocchio-log"
-version = "0.3.0"
-source = "git+https://github.com/febo/pinocchio.git?branch=febo%2Fclose-unstable#246a026bb74c501ba83ea18201000e56c097cb0d"
-dependencies = [
- "pinocchio-log-macro",
-]
-
-[[package]]
-name = "pinocchio-log-macro"
-version = "0.3.0"
-source = "git+https://github.com/febo/pinocchio.git?branch=febo%2Fclose-unstable#246a026bb74c501ba83ea18201000e56c097cb0d"
-dependencies = [
- "quote",
- "regex",
- "syn 1.0.109",
-]
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f89f8ffd986174cefe59448295a004aaf70c3605f30de066f42d27b06188f267"
 
 [[package]]
 name = "pinocchio-pubkey"
-version = "0.2.2"
-source = "git+https://github.com/febo/pinocchio.git?branch=febo%2Fclose-unstable#246a026bb74c501ba83ea18201000e56c097cb0d"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7c8cd934ccaf7915d19049275f77c8888860a2792102a5d9f0b8eafbf670f6a8"
 dependencies = [
  "five8_const",
  "pinocchio",

+ 2 - 2
interface/Cargo.toml

@@ -12,8 +12,8 @@ readme = "./README.md"
 crate-type = ["rlib"]
 
 [dependencies]
-pinocchio = { version = "0.7", git = "https://github.com/febo/pinocchio.git", branch = "febo/close-unstable" }
-pinocchio-pubkey = { version = "0.2", git = "https://github.com/febo/pinocchio.git", branch = "febo/close-unstable" }
+pinocchio = "0.8"
+pinocchio-pubkey = "0.2"
 
 [dev-dependencies]
 strum = "0.27"

+ 70 - 1
interface/src/error.rs

@@ -1,6 +1,6 @@
 //! Error types
 
-use pinocchio::program_error::ProgramError;
+use pinocchio::program_error::{ProgramError, ToStr};
 
 /// Errors that may be returned by the Token program.
 #[derive(Clone, Debug, Eq, PartialEq)]
@@ -59,3 +59,72 @@ impl From<TokenError> for ProgramError {
         ProgramError::Custom(e as u32)
     }
 }
+
+impl ToStr for TokenError {
+    fn to_str<E>(&self) -> &'static str
+    where
+        E: 'static + ToStr + TryFrom<u32>,
+    {
+        match self {
+            TokenError::NotRentExempt => "Error: Lamport balance below rent-exempt threshold",
+            TokenError::InsufficientFunds => "Error: insufficient funds",
+            TokenError::InvalidMint => "Error: Invalid Mint",
+            TokenError::MintMismatch => "Error: Account not associated with this Mint",
+            TokenError::OwnerMismatch => "Error: owner does not match",
+            TokenError::FixedSupply => "Error: the total supply of this token is fixed",
+            TokenError::AlreadyInUse => "Error: account or token already in use",
+            TokenError::InvalidNumberOfProvidedSigners => {
+                "Error: Invalid number of provided signers"
+            }
+            TokenError::InvalidNumberOfRequiredSigners => {
+                "Error: Invalid number of required signers"
+            }
+            TokenError::UninitializedState => "Error: State is uninitialized",
+            TokenError::NativeNotSupported => "Error: Instruction does not support native tokens",
+            TokenError::NonNativeHasBalance => {
+                "Error: Non-native account can only be closed if its balance is zero"
+            }
+            TokenError::InvalidInstruction => "Error: Invalid instruction",
+            TokenError::InvalidState => "Error: Invalid account state for operation",
+            TokenError::Overflow => "Error: Operation overflowed",
+            TokenError::AuthorityTypeNotSupported => {
+                "Error: Account does not support specified authority type"
+            }
+            TokenError::MintCannotFreeze => "Error: This token mint cannot freeze accounts",
+            TokenError::AccountFrozen => "Error: Account is frozen",
+            TokenError::MintDecimalsMismatch => "Error: decimals different from the Mint decimals",
+            TokenError::NonNativeNotSupported => {
+                "Error: Instruction does not support non-native tokens"
+            }
+        }
+    }
+}
+
+impl TryFrom<u32> for TokenError {
+    type Error = ProgramError;
+    fn try_from(value: u32) -> Result<Self, Self::Error> {
+        match value {
+            0 => Ok(TokenError::NotRentExempt),
+            1 => Ok(TokenError::InsufficientFunds),
+            2 => Ok(TokenError::InvalidMint),
+            3 => Ok(TokenError::MintMismatch),
+            4 => Ok(TokenError::OwnerMismatch),
+            5 => Ok(TokenError::FixedSupply),
+            6 => Ok(TokenError::AlreadyInUse),
+            7 => Ok(TokenError::InvalidNumberOfProvidedSigners),
+            8 => Ok(TokenError::InvalidNumberOfRequiredSigners),
+            9 => Ok(TokenError::UninitializedState),
+            10 => Ok(TokenError::NativeNotSupported),
+            11 => Ok(TokenError::NonNativeHasBalance),
+            12 => Ok(TokenError::InvalidInstruction),
+            13 => Ok(TokenError::InvalidState),
+            14 => Ok(TokenError::Overflow),
+            15 => Ok(TokenError::AuthorityTypeNotSupported),
+            16 => Ok(TokenError::MintCannotFreeze),
+            17 => Ok(TokenError::AccountFrozen),
+            18 => Ok(TokenError::MintDecimalsMismatch),
+            19 => Ok(TokenError::NonNativeNotSupported),
+            _ => Err(ProgramError::InvalidArgument),
+        }
+    }
+}

+ 2 - 2
p-token/Cargo.toml

@@ -15,8 +15,8 @@ crate-type = ["cdylib"]
 logging = []
 
 [dependencies]
-pinocchio = { version = "0.7", git = "https://github.com/febo/pinocchio.git", branch = "febo/close-unstable" }
-pinocchio-log = { version = "0.3", git = "https://github.com/febo/pinocchio.git", branch = "febo/close-unstable" }
+pinocchio = "0.8"
+pinocchio-log = { version = "0.4", default-features = false }
 spl-token-interface = { version = "^0", path = "../interface" }
 
 [dev-dependencies]

+ 18 - 6
p-token/src/entrypoint.rs

@@ -1,9 +1,13 @@
 use {
     crate::processor::*,
     pinocchio::{
-        account_info::AccountInfo, default_panic_handler, no_allocator, program_entrypoint,
-        program_error::ProgramError, pubkey::Pubkey, ProgramResult,
+        account_info::AccountInfo,
+        default_panic_handler, no_allocator, program_entrypoint,
+        program_error::{ProgramError, ToStr},
+        pubkey::Pubkey,
+        ProgramResult,
     },
+    spl_token_interface::error::TokenError,
 };
 
 program_entrypoint!(process_instruction);
@@ -12,6 +16,12 @@ no_allocator!();
 // Use the default panic handler.
 default_panic_handler!();
 
+/// Log an error.
+#[cold]
+fn log_error(error: &ProgramError) {
+    pinocchio::log::sol_log(error.to_str::<TokenError>());
+}
+
 /// Process an instruction.
 ///
 /// In the first stage, the entrypoint checks the discriminator of the
@@ -29,15 +39,17 @@ pub fn process_instruction(
         return Err(ProgramError::InvalidInstructionData);
     };
 
-    if *discriminator == 255 {
+    let result = if *discriminator == 255 {
         // 255 - Batch
         #[cfg(feature = "logging")]
         pinocchio::msg!("Instruction: Batch");
 
-        return process_batch(accounts, remaining);
-    }
+        process_batch(accounts, remaining)
+    } else {
+        inner_process_instruction(accounts, instruction_data)
+    };
 
-    inner_process_instruction(accounts, instruction_data)
+    result.inspect_err(log_error)
 }
 
 /// Process a "regular" instruction.

+ 4 - 4
p-token/src/processor/mod.rs

@@ -74,10 +74,10 @@ const MAX_FORMATTED_DIGITS: usize = u8::MAX as usize + 2;
 /// Checks that the account is owned by the expected program.
 #[inline(always)]
 fn check_account_owner(account_info: &AccountInfo) -> ProgramResult {
-    if &TOKEN_PROGRAM_ID != account_info.owner() {
-        Err(ProgramError::IncorrectProgramId)
-    } else {
+    if account_info.is_owned_by(&TOKEN_PROGRAM_ID) {
         Ok(())
+    } else {
+        Err(ProgramError::IncorrectProgramId)
     }
 }
 
@@ -98,7 +98,7 @@ fn validate_owner(
     }
 
     if owner_account_info.data_len() == Multisig::LEN
-        && owner_account_info.owner() == &TOKEN_PROGRAM_ID
+        && owner_account_info.is_owned_by(&TOKEN_PROGRAM_ID)
     {
         // SAFETY: the caller guarantees that there are no mutable borrows of
         // `owner_account_info` account data and the `load` validates that the

+ 0 - 1
package.json

@@ -33,7 +33,6 @@
     "fixtures:run": "zx ./scripts/rust/fixtures.mjs run",
     "interface:format": "zx ./scripts/rust/format.mjs interface",
     "interface:lint": "zx ./scripts/rust/lint.mjs interface"
-
   },
   "devDependencies": {
     "@codama/renderers-js": "^1.2.7",