Skip to content

Commit 4c46748

Browse files
authored
p-token: Add error logging (solana-program#41)
* Add fixtures test script * Add error logging * Update pinocchio dependencies * Fix formatting
1 parent 261bbdd commit 4c46748

File tree

7 files changed

+105
-35
lines changed

7 files changed

+105
-35
lines changed

Cargo.lock

Lines changed: 9 additions & 19 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

interface/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ readme = "./README.md"
1212
crate-type = ["rlib"]
1313

1414
[dependencies]
15-
pinocchio = { version = "0.7", git = "https://github.com/febo/pinocchio.git", branch = "febo/close-unstable" }
16-
pinocchio-pubkey = { version = "0.2", git = "https://github.com/febo/pinocchio.git", branch = "febo/close-unstable" }
15+
pinocchio = "0.8"
16+
pinocchio-pubkey = "0.2"
1717

1818
[dev-dependencies]
1919
strum = "0.27"

interface/src/error.rs

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Error types
22
3-
use pinocchio::program_error::ProgramError;
3+
use pinocchio::program_error::{ProgramError, ToStr};
44

55
/// Errors that may be returned by the Token program.
66
#[derive(Clone, Debug, Eq, PartialEq)]
@@ -59,3 +59,72 @@ impl From<TokenError> for ProgramError {
5959
ProgramError::Custom(e as u32)
6060
}
6161
}
62+
63+
impl ToStr for TokenError {
64+
fn to_str<E>(&self) -> &'static str
65+
where
66+
E: 'static + ToStr + TryFrom<u32>,
67+
{
68+
match self {
69+
TokenError::NotRentExempt => "Error: Lamport balance below rent-exempt threshold",
70+
TokenError::InsufficientFunds => "Error: insufficient funds",
71+
TokenError::InvalidMint => "Error: Invalid Mint",
72+
TokenError::MintMismatch => "Error: Account not associated with this Mint",
73+
TokenError::OwnerMismatch => "Error: owner does not match",
74+
TokenError::FixedSupply => "Error: the total supply of this token is fixed",
75+
TokenError::AlreadyInUse => "Error: account or token already in use",
76+
TokenError::InvalidNumberOfProvidedSigners => {
77+
"Error: Invalid number of provided signers"
78+
}
79+
TokenError::InvalidNumberOfRequiredSigners => {
80+
"Error: Invalid number of required signers"
81+
}
82+
TokenError::UninitializedState => "Error: State is uninitialized",
83+
TokenError::NativeNotSupported => "Error: Instruction does not support native tokens",
84+
TokenError::NonNativeHasBalance => {
85+
"Error: Non-native account can only be closed if its balance is zero"
86+
}
87+
TokenError::InvalidInstruction => "Error: Invalid instruction",
88+
TokenError::InvalidState => "Error: Invalid account state for operation",
89+
TokenError::Overflow => "Error: Operation overflowed",
90+
TokenError::AuthorityTypeNotSupported => {
91+
"Error: Account does not support specified authority type"
92+
}
93+
TokenError::MintCannotFreeze => "Error: This token mint cannot freeze accounts",
94+
TokenError::AccountFrozen => "Error: Account is frozen",
95+
TokenError::MintDecimalsMismatch => "Error: decimals different from the Mint decimals",
96+
TokenError::NonNativeNotSupported => {
97+
"Error: Instruction does not support non-native tokens"
98+
}
99+
}
100+
}
101+
}
102+
103+
impl TryFrom<u32> for TokenError {
104+
type Error = ProgramError;
105+
fn try_from(value: u32) -> Result<Self, Self::Error> {
106+
match value {
107+
0 => Ok(TokenError::NotRentExempt),
108+
1 => Ok(TokenError::InsufficientFunds),
109+
2 => Ok(TokenError::InvalidMint),
110+
3 => Ok(TokenError::MintMismatch),
111+
4 => Ok(TokenError::OwnerMismatch),
112+
5 => Ok(TokenError::FixedSupply),
113+
6 => Ok(TokenError::AlreadyInUse),
114+
7 => Ok(TokenError::InvalidNumberOfProvidedSigners),
115+
8 => Ok(TokenError::InvalidNumberOfRequiredSigners),
116+
9 => Ok(TokenError::UninitializedState),
117+
10 => Ok(TokenError::NativeNotSupported),
118+
11 => Ok(TokenError::NonNativeHasBalance),
119+
12 => Ok(TokenError::InvalidInstruction),
120+
13 => Ok(TokenError::InvalidState),
121+
14 => Ok(TokenError::Overflow),
122+
15 => Ok(TokenError::AuthorityTypeNotSupported),
123+
16 => Ok(TokenError::MintCannotFreeze),
124+
17 => Ok(TokenError::AccountFrozen),
125+
18 => Ok(TokenError::MintDecimalsMismatch),
126+
19 => Ok(TokenError::NonNativeNotSupported),
127+
_ => Err(ProgramError::InvalidArgument),
128+
}
129+
}
130+
}

p-token/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ crate-type = ["cdylib"]
1515
logging = []
1616

1717
[dependencies]
18-
pinocchio = { version = "0.7", git = "https://github.com/febo/pinocchio.git", branch = "febo/close-unstable" }
19-
pinocchio-log = { version = "0.3", git = "https://github.com/febo/pinocchio.git", branch = "febo/close-unstable" }
18+
pinocchio = "0.8"
19+
pinocchio-log = { version = "0.4", default-features = false }
2020
spl-token-interface = { version = "^0", path = "../interface" }
2121

2222
[dev-dependencies]

p-token/src/entrypoint.rs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
use {
22
crate::processor::*,
33
pinocchio::{
4-
account_info::AccountInfo, default_panic_handler, no_allocator, program_entrypoint,
5-
program_error::ProgramError, pubkey::Pubkey, ProgramResult,
4+
account_info::AccountInfo,
5+
default_panic_handler, no_allocator, program_entrypoint,
6+
program_error::{ProgramError, ToStr},
7+
pubkey::Pubkey,
8+
ProgramResult,
69
},
10+
spl_token_interface::error::TokenError,
711
};
812

913
program_entrypoint!(process_instruction);
@@ -12,6 +16,12 @@ no_allocator!();
1216
// Use the default panic handler.
1317
default_panic_handler!();
1418

19+
/// Log an error.
20+
#[cold]
21+
fn log_error(error: &ProgramError) {
22+
pinocchio::log::sol_log(error.to_str::<TokenError>());
23+
}
24+
1525
/// Process an instruction.
1626
///
1727
/// In the first stage, the entrypoint checks the discriminator of the
@@ -29,15 +39,17 @@ pub fn process_instruction(
2939
return Err(ProgramError::InvalidInstructionData);
3040
};
3141

32-
if *discriminator == 255 {
42+
let result = if *discriminator == 255 {
3343
// 255 - Batch
3444
#[cfg(feature = "logging")]
3545
pinocchio::msg!("Instruction: Batch");
3646

37-
return process_batch(accounts, remaining);
38-
}
47+
process_batch(accounts, remaining)
48+
} else {
49+
inner_process_instruction(accounts, instruction_data)
50+
};
3951

40-
inner_process_instruction(accounts, instruction_data)
52+
result.inspect_err(log_error)
4153
}
4254

4355
/// Process a "regular" instruction.

p-token/src/processor/mod.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,10 @@ const MAX_FORMATTED_DIGITS: usize = u8::MAX as usize + 2;
7474
/// Checks that the account is owned by the expected program.
7575
#[inline(always)]
7676
fn check_account_owner(account_info: &AccountInfo) -> ProgramResult {
77-
if &TOKEN_PROGRAM_ID != account_info.owner() {
78-
Err(ProgramError::IncorrectProgramId)
79-
} else {
77+
if account_info.is_owned_by(&TOKEN_PROGRAM_ID) {
8078
Ok(())
79+
} else {
80+
Err(ProgramError::IncorrectProgramId)
8181
}
8282
}
8383

@@ -98,7 +98,7 @@ fn validate_owner(
9898
}
9999

100100
if owner_account_info.data_len() == Multisig::LEN
101-
&& owner_account_info.owner() == &TOKEN_PROGRAM_ID
101+
&& owner_account_info.is_owned_by(&TOKEN_PROGRAM_ID)
102102
{
103103
// SAFETY: the caller guarantees that there are no mutable borrows of
104104
// `owner_account_info` account data and the `load` validates that the

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
"fixtures:run": "zx ./scripts/rust/fixtures.mjs run",
3434
"interface:format": "zx ./scripts/rust/format.mjs interface",
3535
"interface:lint": "zx ./scripts/rust/lint.mjs interface"
36-
3736
},
3837
"devDependencies": {
3938
"@codama/renderers-js": "^1.2.7",

0 commit comments

Comments
 (0)