use {
std::{
result::Result as ResultGeneric,
},
};
pub type ProgramResult = ResultGeneric<(), ProgramError>;
其实就是一个使用了ProgramError作为Err部分的Result类型枚举。
错误类型
上面提到的ProgramError的定义为:
/// Reasons the program may fail
#[derive(Clone, Debug, Deserialize, Eq, Error, PartialEq, Serialize)]
pub enum ProgramError {
/// Allows on-chain programs to implement program-specific error types and see them returned
/// by the Solana runtime. A program-specific error may be any type that is represented as
/// or serialized to a u32 integer.
#[error("Custom program error: {0:#x}")]
Custom(u32),
#[error("The arguments provided to a program instruction were invalid")]
InvalidArgument,
#[error("An instruction's data contents was invalid")]
InvalidInstructionData,
#[error("An account's data contents was invalid")]
InvalidAccountData,
#[error("An account's data was too small")]
AccountDataTooSmall,
#[error("An account's balance was too small to complete the instruction")]
InsufficientFunds,
#[error("The account did not have the expected program id")]
IncorrectProgramId,
#[error("A signature was required but not found")]
MissingRequiredSignature,
#[error("An initialize instruction was sent to an account that has already been initialized")]
AccountAlreadyInitialized,
#[error("An attempt to operate on an account that hasn't been initialized")]
UninitializedAccount,
#[error("The instruction expected additional account keys")]
NotEnoughAccountKeys,
#[error("Failed to borrow a reference to account data, already borrowed")]
AccountBorrowFailed,
#[error("Length of the seed is too long for address generation")]
MaxSeedLengthExceeded,
#[error("Provided seeds do not result in a valid address")]
InvalidSeeds,
#[error("IO Error: {0}")]
BorshIoError(String),
#[error("An account does not have enough lamports to be rent-exempt")]
AccountNotRentExempt,
#[error("Unsupported sysvar")]
UnsupportedSysvar,
#[error("Provided owner is not allowed")]
IllegalOwner,
#[error("Accounts data allocations exceeded the maximum allowed per transaction")]
MaxAccountsDataAllocationsExceeded,
#[error("Account data reallocation was invalid")]
InvalidRealloc,
#[error("Instruction trace length exceeded the maximum allowed per transaction")]
MaxInstructionTraceLengthExceeded,
#[error("Builtin programs must consume compute units")]
BuiltinProgramsMustConsumeComputeUnits,
}
impl From<HelloWorldError> for ProgramError {
fn from(e: HelloWorldError) -> Self {
ProgramError::Custom(e as u32)
}
}
直接将枚举的值,转换成了Custom里面的错误码。
错误码有了,但是错误码对应的意义是什么呢?
impl PrintProgramError for HelloWorldError {
fn print<E>(&self)
where
E: 'static + std::error::Error + DecodeError<E> + PrintProgramError + FromPrimitive,
{
match self {
HelloWorldError::NotOwnedByHelloWrold => msg!("Error: Greeted account does not have the correct program id!"),
}
}
}
这里通过PrintProgramError trate的实现,来定义其错误消息。
这样在出错的时候,返回相应错误。
if greeting_account.owner != program_id {
msg!("Greeted account does not have the correct program id");
return Err(HelloWorldError::NotOwnedByHelloWrold.into());
}
通过into直接转换。
InvalidArgument:
参数无效。当传递给合约指令的参数不符合预期时,会返回此错误。
pub fn process_instruction( _program_id: &Pubkey, _accounts: &[AccountInfo],_instruction_data: &[u8],
) -> ProgramResult {
msg!("Hello World Rust program entrypoint");
//碰到参数无效错误,返回错误
Err(ProgramError::InvalidArgument)
}