Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error redesign #1462

Merged
merged 119 commits into from
Feb 20, 2022
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
119 commits
Select commit Hold shift + click to select a range
6ab5f86
WIP
paul-schaaf Feb 17, 2022
c1b7ffb
accounts work
paul-schaaf Feb 17, 2022
fefeee9
WIP
paul-schaaf Feb 17, 2022
c699deb
WIP
paul-schaaf Feb 17, 2022
26099aa
WIP
paul-schaaf Feb 17, 2022
826061e
constraints
paul-schaaf Feb 17, 2022
b158759
constraints
paul-schaaf Feb 17, 2022
31d63cb
constraints
paul-schaaf Feb 17, 2022
bbf4c93
WIP
paul-schaaf Feb 17, 2022
ff49753
LANG COMPILES
paul-schaaf Feb 17, 2022
d4c6133
fmt and clippy
paul-schaaf Feb 17, 2022
8093770
require!
paul-schaaf Feb 17, 2022
b2621c3
WIP
paul-schaaf Feb 17, 2022
dee9580
WIP
paul-schaaf Feb 17, 2022
d476718
WIP
paul-schaaf Feb 17, 2022
0903b06
WIP
paul-schaaf Feb 17, 2022
d5b840b
WIP
paul-schaaf Feb 17, 2022
3a433f4
WIP
paul-schaaf Feb 17, 2022
e7f1fcf
WIP
paul-schaaf Feb 17, 2022
5677031
LANG AND BARE-BONES PROGRAM COMPILES
paul-schaaf Feb 17, 2022
fe0a48f
basic program now also works with build-bpf instead of just build
paul-schaaf Feb 17, 2022
ea5edcd
WIP
paul-schaaf Feb 17, 2022
ffb113e
remove program id from error for now
paul-schaaf Feb 18, 2022
c5dc814
error! now returns Error instead of Err(Error)
paul-schaaf Feb 18, 2022
c501266
remove unused code
paul-schaaf Feb 18, 2022
bf1f0ad
error_with_account_name
paul-schaaf Feb 18, 2022
37c9998
ProgramErrorWithoutOrigin and errors from types
paul-schaaf Feb 18, 2022
fe460c3
fix spl token
paul-schaaf Feb 18, 2022
25815bb
add todo
paul-schaaf Feb 18, 2022
573f507
make client compile
paul-schaaf Feb 18, 2022
211e59f
clippy
paul-schaaf Feb 18, 2022
4e12959
dont use format to error_name
paul-schaaf Feb 19, 2022
34dbacb
error_without_origin for DeclaredProgramIdMismatch error
paul-schaaf Feb 19, 2022
fe050d6
add all error structures to prelude
paul-schaaf Feb 19, 2022
8087460
fix tests
paul-schaaf Feb 19, 2022
234ca57
adjust idl creation to use error_codes instead of error attribute
paul-schaaf Feb 19, 2022
5667345
fix error tests
paul-schaaf Feb 19, 2022
08a48d4
fmt
paul-schaaf Feb 19, 2022
8671951
add todos
paul-schaaf Feb 19, 2022
aa64f5a
fix basic4
paul-schaaf Feb 19, 2022
32a20dc
fmt
paul-schaaf Feb 19, 2022
0810228
fix cashiers-check
paul-schaaf Feb 19, 2022
11b8a77
error_with_account_name for all constraint errors
paul-schaaf Feb 19, 2022
a772cfc
fix compile errors
paul-schaaf Feb 19, 2022
5411764
fix basic3 example
paul-schaaf Feb 19, 2022
fbd8037
fmt
paul-schaaf Feb 19, 2022
121080a
fix interface test
paul-schaaf Feb 19, 2022
6a51b4a
fix chat tests
paul-schaaf Feb 19, 2022
365fce1
close now uses error_without_origin
paul-schaaf Feb 19, 2022
646a60d
try_account ix deser now uses error_without_origin
paul-schaaf Feb 19, 2022
65f6126
fix lockup test
paul-schaaf Feb 19, 2022
c56e401
ido pool
paul-schaaf Feb 19, 2022
ea4532c
fix misc test
paul-schaaf Feb 19, 2022
0f8d1ec
fix multisig test
paul-schaaf Feb 19, 2022
cf42ee4
fix swap test
paul-schaaf Feb 19, 2022
51706fa
AnchorResult -> Result
paul-schaaf Feb 19, 2022
ef4cd3f
entry function use ProgramResult with full path
paul-schaaf Feb 19, 2022
ecd9cb8
anchor_lang::Result -> Result
paul-schaaf Feb 19, 2022
9b944b6
fmt
paul-schaaf Feb 19, 2022
70b19ea
clippy
paul-schaaf Feb 19, 2022
59d0f7f
fmt
paul-schaaf Feb 19, 2022
a72c384
add Result<()> spl crate compile
paul-schaaf Feb 19, 2022
0152d9a
spl dex crate compile
paul-schaaf Feb 19, 2022
c4f7468
fix tests
paul-schaaf Feb 19, 2022
10553cb
fix composite test
paul-schaaf Feb 19, 2022
0fe7409
fmt
paul-schaaf Feb 19, 2022
1761d57
fix events test
paul-schaaf Feb 19, 2022
ac83700
fix examples tests
paul-schaaf Feb 19, 2022
207857d
fix more tests
paul-schaaf Feb 19, 2022
5528173
revert custom-coder back to master
paul-schaaf Feb 19, 2022
599461f
Merge branch 'master' into error-redesign
paul-schaaf Feb 19, 2022
e953f17
fix floats test
paul-schaaf Feb 19, 2022
64ab4c0
run all test except those with submodules
paul-schaaf Feb 19, 2022
7eb0d06
fix interface tests
paul-schaaf Feb 19, 2022
8deaeff
fix TODOs
paul-schaaf Feb 19, 2022
571210d
fix todos
paul-schaaf Feb 19, 2022
61eb0eb
fix todos
paul-schaaf Feb 19, 2022
f9323f3
fix todo
paul-schaaf Feb 19, 2022
17290eb
remove todo
paul-schaaf Feb 19, 2022
ddae8c6
fmt
paul-schaaf Feb 19, 2022
1946f2f
fix auctionhouse tests
paul-schaaf Feb 19, 2022
c5fca8a
swap was already working
paul-schaaf Feb 19, 2022
a98b228
fix cfo test
paul-schaaf Feb 19, 2022
6f111e1
add docs todo
paul-schaaf Feb 19, 2022
fdf6578
error_codes -> error_code
paul-schaaf Feb 19, 2022
bce05b1
move error parsing into syn crate
paul-schaaf Feb 19, 2022
2630cdd
refactor error
paul-schaaf Feb 20, 2022
30cbcb9
update docs
paul-schaaf Feb 20, 2022
5abac35
fix error macro
paul-schaaf Feb 20, 2022
064e527
add require! test
paul-schaaf Feb 20, 2022
21f3281
Fix error test
paul-schaaf Feb 20, 2022
283f43c
lang: add bail! macro
paul-schaaf Feb 20, 2022
ef2f181
docs
paul-schaaf Feb 20, 2022
2bb6be8
lang: fix ProgramError logging
paul-schaaf Feb 20, 2022
43a200f
tests: add tests for error logging
paul-schaaf Feb 20, 2022
007eafc
ci: turn off fail-fast for matrix
paul-schaaf Feb 20, 2022
7647c04
lang: remove TODO
paul-schaaf Feb 20, 2022
e6ea718
fmt
paul-schaaf Feb 20, 2022
39209ca
ts: ts library can now also parse real tx errors instead of just simu…
paul-schaaf Feb 20, 2022
c8904ae
tests: fix error tests
paul-schaaf Feb 20, 2022
69f89a3
tests: add sleep to errors test to allow logs to come in
paul-schaaf Feb 20, 2022
13dcede
tests: fix sleep
paul-schaaf Feb 20, 2022
3692e9c
tests fix sleep placement
paul-schaaf Feb 20, 2022
39e1719
remove dead todo
paul-schaaf Feb 20, 2022
c99d335
docs: changelog
paul-schaaf Feb 20, 2022
22fbe6c
lang: add with_source method on Error type so ProgramErrors can be en…
paul-schaaf Feb 20, 2022
c83e28f
lang: remove error_without_origin
paul-schaaf Feb 20, 2022
34ea949
pe.into() -> Into::into
paul-schaaf Feb 20, 2022
93b6bd3
.into() -> Error::from()
paul-schaaf Feb 20, 2022
a7ae6ae
bail! -> err!
paul-schaaf Feb 20, 2022
d85a310
tests: use err!
paul-schaaf Feb 20, 2022
62b9902
lang: use .map_err again in close
paul-schaaf Feb 20, 2022
88e4510
lang: import anchor_lang::Result
paul-schaaf Feb 20, 2022
9f40e76
tests: fix lockup test
paul-schaaf Feb 20, 2022
aeca9a3
try not using Error::from
armaniferrante Feb 20, 2022
0148808
Update lang/attribute/interface/src/lib.rs
armaniferrante Feb 20, 2022
68c5188
fmt import
armaniferrante Feb 20, 2022
9dc873b
fmt more imports
armaniferrante Feb 20, 2022
a3bb227
update submodule pointers
armaniferrante Feb 20, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 18 additions & 17 deletions lang/attribute/account/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,18 +146,18 @@ pub fn account(
// It's expected on-chain programs deserialize via zero-copy.
#[automatically_derived]
impl #impl_gen anchor_lang::AccountDeserialize for #account_name #type_gen #where_clause {
fn try_deserialize(buf: &mut &[u8]) -> std::result::Result<Self, ProgramError> {
fn try_deserialize(buf: &mut &[u8]) -> anchor_lang::AnchorResult<Self> {
if buf.len() < #discriminator.len() {
return Err(anchor_lang::error::ErrorCode::AccountDiscriminatorNotFound.into());
return anchor_lang::anchor_attribute_error::error!(anchor_lang::error::ErrorCode::AccountDiscriminatorNotFound);
}
let given_disc = &buf[..8];
if &#discriminator != given_disc {
return Err(anchor_lang::error::ErrorCode::AccountDiscriminatorMismatch.into());
return anchor_lang::anchor_attribute_error::error!(anchor_lang::error::ErrorCode::AccountDiscriminatorMismatch);
}
Self::try_deserialize_unchecked(buf)
}

fn try_deserialize_unchecked(buf: &mut &[u8]) -> std::result::Result<Self, ProgramError> {
fn try_deserialize_unchecked(buf: &mut &[u8]) -> anchor_lang::AnchorResult<Self> {
let data: &[u8] = &buf[8..];
// Re-interpret raw bytes into the POD data structure.
let account = anchor_lang::__private::bytemuck::from_bytes(data);
Expand All @@ -175,34 +175,35 @@ pub fn account(

#[automatically_derived]
impl #impl_gen anchor_lang::AccountSerialize for #account_name #type_gen #where_clause {
fn try_serialize<W: std::io::Write>(&self, writer: &mut W) -> std::result::Result<(), ProgramError> {
writer.write_all(&#discriminator).map_err(|_| anchor_lang::error::ErrorCode::AccountDidNotSerialize)?;
AnchorSerialize::serialize(
self,
writer
)
.map_err(|_| anchor_lang::error::ErrorCode::AccountDidNotSerialize)?;
fn try_serialize<W: std::io::Write>(&self, writer: &mut W) -> AnchorResult<()> {
if writer.write_all(&#discriminator).is_err() {
return anchor_lang::anchor_attribute_error::error!(anchor_lang::error::ErrorCode::AccountDidNotSerialize);
}

if AnchorSerialize::serialize(self, writer).is_err() {
return anchor_lang::anchor_attribute_error::error!(anchor_lang::error::ErrorCode::AccountDidNotSerialize);
}
Ok(())
}
}

#[automatically_derived]
impl #impl_gen anchor_lang::AccountDeserialize for #account_name #type_gen #where_clause {
fn try_deserialize(buf: &mut &[u8]) -> std::result::Result<Self, ProgramError> {
fn try_deserialize(buf: &mut &[u8]) -> anchor_lang::AnchorResult<Self> {
if buf.len() < #discriminator.len() {
return Err(anchor_lang::error::ErrorCode::AccountDiscriminatorNotFound.into());
return anchor_lang::anchor_attribute_error::error!(anchor_lang::error::ErrorCode::AccountDiscriminatorNotFound);
}
let given_disc = &buf[..8];
if &#discriminator != given_disc {
return Err(anchor_lang::error::ErrorCode::AccountDiscriminatorMismatch.into());
return anchor_lang::anchor_attribute_error::error!(anchor_lang::error::ErrorCode::AccountDiscriminatorMismatch);
}
Self::try_deserialize_unchecked(buf)
}

fn try_deserialize_unchecked(buf: &mut &[u8]) -> std::result::Result<Self, ProgramError> {
fn try_deserialize_unchecked(buf: &mut &[u8]) -> anchor_lang::AnchorResult<Self> {
let mut data: &[u8] = &buf[8..];
AnchorDeserialize::deserialize(&mut data)
.map_err(|_| anchor_lang::error::ErrorCode::AccountDidNotDeserialize.into())
let temp = AnchorDeserialize::deserialize(&mut data);
temp.or_else(|_| anchor_lang::anchor_attribute_error::error!(anchor_lang::error::ErrorCode::AccountDidNotDeserialize))
}
}

Expand Down
61 changes: 59 additions & 2 deletions lang/attribute/error/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
extern crate proc_macro;

use proc_macro::TokenStream;
use quote::quote;

use anchor_syn::codegen::error as error_codegen;
use anchor_syn::parser::error as error_parser;
use anchor_syn::ErrorArgs;
use syn::parse_macro_input;
use syn::{
parse::{Parse, Result as ParseResult},
parse_macro_input, Expr, Token,
};

/// Generates `Error` and `type Result<T> = Result<T, Error>` types to be
/// used as return types from Anchor instruction handlers. Importantly, the
Expand Down Expand Up @@ -47,7 +53,7 @@ use syn::parse_macro_input;
/// The `#[msg(..)]` attribute is inert, and is used only as a marker so that
/// parsers and IDLs can map error codes to error messages.
#[proc_macro_attribute]
pub fn error(
pub fn error_codes(
args: proc_macro::TokenStream,
input: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
Expand All @@ -59,3 +65,54 @@ pub fn error(
let error = error_codegen::generate(error_parser::parse(&mut error_enum, args));
proc_macro::TokenStream::from(error)
}

#[proc_macro]
pub fn error(ts: proc_macro::TokenStream) -> TokenStream {
let file = file!();
let line = line!();
let input = parse_macro_input!(ts as ErrorInput);
let error_code = input.error_code;
let error_msg_inputs = input.error_msg_inputs;
let error_msg_inputs = if error_msg_inputs.is_empty() {
quote! {
#error_code.to_string()
}
} else {
quote! {
format!(#error_code.to_string(), #(#error_msg_inputs),*)
}
};
quote! {
Err(anchor_lang::error::Error::from(
anchor_lang::error::AnchorError {
program_id: None,
error_code_string: format!("{:?}", #error_code), // TODO: dont use format here
error_code_number: #error_code.into(),
error_msg: #error_msg_inputs,
source: anchor_lang::error::Source {
filename: #file,
line: #line
}
}))
}
.into()
}

struct ErrorInput {
error_code: Expr,
error_msg_inputs: Vec<Expr>,
}

impl Parse for ErrorInput {
fn parse(stream: syn::parse::ParseStream) -> ParseResult<Self> {
let error_code = stream.call(Expr::parse)?;
let mut error_msg_inputs = vec![];
while stream.parse::<Token![,]>().is_ok() {
error_msg_inputs.push(stream.call(Expr::parse)?);
}
Ok(Self {
error_code,
error_msg_inputs,
})
}
}
6 changes: 3 additions & 3 deletions lang/attribute/interface/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use syn::parse_macro_input;
///
/// #[interface]
/// pub trait Auth<'info, T: Accounts<'info>> {
/// fn is_authorized(ctx: Context<T>, current: u64, new: u64) -> ProgramResult;
/// fn is_authorized(ctx: Context<T>, current: u64, new: u64) -> AnchorResult<()>;
/// }
///
/// #[program]
Expand Down Expand Up @@ -104,7 +104,7 @@ use syn::parse_macro_input;
/// pub struct CounterAuth;
///
/// impl<'info> Auth<'info, Empty> for CounterAuth {
/// fn is_authorized(_ctx: Context<Empty>, current: u64, new: u64) -> ProgramResult {
/// fn is_authorized(_ctx: Context<Empty>, current: u64, new: u64) -> AnchorResult<()> {
/// if current % 2 == 0 {
/// if new % 2 == 0 {
/// return Err(ProgramError::Custom(50)); // Arbitrary error code.
Expand Down Expand Up @@ -200,7 +200,7 @@ pub fn interface(
pub fn #method_name<'a,'b, 'c, 'info, T: anchor_lang::Accounts<'info> + anchor_lang::ToAccountMetas + anchor_lang::ToAccountInfos<'info>>(
ctx: anchor_lang::context::CpiContext<'a, 'b, 'c, 'info, T>,
#(#args),*
) -> anchor_lang::solana_program::entrypoint::ProgramResult {
) -> anchor_lang::AnchorResult {
paul-schaaf marked this conversation as resolved.
Show resolved Hide resolved
#args_struct

let ix = {
Expand Down
2 changes: 1 addition & 1 deletion lang/derive/accounts/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use syn::parse_macro_input;
///
/// ```ignore
/// ...
/// pub fn initialize(ctx: Context<Create>, bump: u8, authority: Pubkey, data: u64) -> ProgramResult {
/// pub fn initialize(ctx: Context<Create>, bump: u8, authority: Pubkey, data: u64) -> AnchorResult<()> {
/// ...
/// Ok(())
/// }
Expand Down
31 changes: 15 additions & 16 deletions lang/src/accounts/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ use crate::*;
use solana_program::account_info::AccountInfo;
use solana_program::entrypoint::ProgramResult;
use solana_program::instruction::AccountMeta;
use solana_program::program_error::ProgramError;
use solana_program::pubkey::Pubkey;
use std::collections::BTreeMap;
use std::fmt;
Expand Down Expand Up @@ -44,7 +43,7 @@ use std::ops::{Deref, DerefMut};
/// #[program]
/// mod hello_anchor {
/// use super::*;
/// pub fn set_data(ctx: Context<SetData>, data: u64) -> ProgramResult {
/// pub fn set_data(ctx: Context<SetData>, data: u64) -> AnchorResult<()> {
/// if (*ctx.accounts.auth_account).authorized {
/// (*ctx.accounts.my_account).data = data;
/// }
Expand Down Expand Up @@ -161,7 +160,7 @@ use std::ops::{Deref, DerefMut};
/// pub fn set_initial_admin(
/// ctx: Context<SetInitialAdmin>,
/// admin_key: Pubkey
/// ) -> ProgramResult {
/// ) -> AnchorResult<()> {
/// ctx.accounts.admin_settings.admin_key = admin_key;
/// Ok(())
/// }
Expand Down Expand Up @@ -243,12 +242,12 @@ impl<'a, T: AccountSerialize + AccountDeserialize + Owner + Clone> Account<'a, T

/// Deserializes the given `info` into a `Account`.
#[inline(never)]
pub fn try_from(info: &AccountInfo<'a>) -> Result<Account<'a, T>, ProgramError> {
pub fn try_from(info: &AccountInfo<'a>) -> AnchorResult<Account<'a, T>> {
armaniferrante marked this conversation as resolved.
Show resolved Hide resolved
if info.owner == &system_program::ID && info.lamports() == 0 {
return Err(ErrorCode::AccountNotInitialized.into());
return anchor_attribute_error::error!(ErrorCode::AccountNotInitialized);
}
if info.owner != &T::owner() {
return Err(ErrorCode::AccountOwnedByWrongProgram.into());
return anchor_attribute_error::error!(ErrorCode::AccountOwnedByWrongProgram);
}
let mut data: &[u8] = &info.try_borrow_data()?;
Ok(Account::new(info.clone(), T::try_deserialize(&mut data)?))
Expand All @@ -258,12 +257,12 @@ impl<'a, T: AccountSerialize + AccountDeserialize + Owner + Clone> Account<'a, T
/// the account discriminator. Be careful when using this and avoid it if
/// possible.
#[inline(never)]
pub fn try_from_unchecked(info: &AccountInfo<'a>) -> Result<Account<'a, T>, ProgramError> {
pub fn try_from_unchecked(info: &AccountInfo<'a>) -> AnchorResult<Account<'a, T>> {
if info.owner == &system_program::ID && info.lamports() == 0 {
return Err(ErrorCode::AccountNotInitialized.into());
return anchor_attribute_error::error!(ErrorCode::AccountNotInitialized);
}
if info.owner != &T::owner() {
return Err(ErrorCode::AccountOwnedByWrongProgram.into());
return anchor_attribute_error::error!(ErrorCode::AccountOwnedByWrongProgram);
}
let mut data: &[u8] = &info.try_borrow_data()?;
Ok(Account::new(
Expand All @@ -274,7 +273,7 @@ impl<'a, T: AccountSerialize + AccountDeserialize + Owner + Clone> Account<'a, T

/// Reloads the account from storage. This is useful, for example, when
/// observing side effects after CPI.
pub fn reload(&mut self) -> ProgramResult {
pub fn reload(&mut self) -> AnchorResult<()> {
let mut data: &[u8] = &self.info.try_borrow_data()?;
self.account = T::try_deserialize(&mut data)?;
Ok(())
Expand All @@ -288,15 +287,15 @@ impl<'a, T: AccountSerialize + AccountDeserialize + Owner + Clone> Account<'a, T
///
/// Instead of this:
/// ```ignore
/// pub fn new_user(ctx: Context<CreateUser>, new_user:User) -> ProgramResult {
/// pub fn new_user(ctx: Context<CreateUser>, new_user:User) -> AnchorResult<()> {
/// (*ctx.accounts.user_to_create).name = new_user.name;
/// (*ctx.accounts.user_to_create).age = new_user.age;
/// (*ctx.accounts.user_to_create).address = new_user.address;
/// }
/// ```
/// You can do this:
/// ```ignore
/// pub fn new_user(ctx: Context<CreateUser>, new_user:User) -> ProgramResult {
/// pub fn new_user(ctx: Context<CreateUser>, new_user:User) -> AnchorResult<()> {
/// ctx.accounts.user_to_create.set_inner(new_user);
/// }
/// ```
Expand All @@ -316,9 +315,9 @@ where
accounts: &mut &[AccountInfo<'info>],
_ix_data: &[u8],
_bumps: &mut BTreeMap<String, u8>,
) -> Result<Self, ProgramError> {
) -> AnchorResult<Self> {
if accounts.is_empty() {
return Err(ErrorCode::AccountNotEnoughKeys.into());
return anchor_attribute_error::error!(ErrorCode::AccountNotEnoughKeys);
}
let account = &accounts[0];
*accounts = &accounts[1..];
Expand All @@ -329,7 +328,7 @@ where
impl<'info, T: AccountSerialize + AccountDeserialize + Owner + Clone> AccountsExit<'info>
for Account<'info, T>
{
fn exit(&self, program_id: &Pubkey) -> ProgramResult {
fn exit(&self, program_id: &Pubkey) -> AnchorResult<()> {
// Only persist if the owner is the current program.
if &T::owner() == program_id {
let info = self.to_account_info();
Expand All @@ -345,7 +344,7 @@ impl<'info, T: AccountSerialize + AccountDeserialize + Owner + Clone> AccountsEx
impl<'info, T: AccountSerialize + AccountDeserialize + Owner + Clone> AccountsClose<'info>
for Account<'info, T>
{
fn close(&self, sol_destination: AccountInfo<'info>) -> ProgramResult {
fn close(&self, sol_destination: AccountInfo<'info>) -> AnchorResult<()> {
crate::common::close(self.to_account_info(), sol_destination)
}
}
Expand Down
7 changes: 3 additions & 4 deletions lang/src/accounts/account_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@
//! should be used instead.

use crate::error::ErrorCode;
use crate::{Accounts, AccountsExit, ToAccountInfos, ToAccountMetas};
use crate::{Accounts, AccountsExit, AnchorResult, ToAccountInfos, ToAccountMetas};
use solana_program::account_info::AccountInfo;
use solana_program::instruction::AccountMeta;
use solana_program::program_error::ProgramError;
use solana_program::pubkey::Pubkey;
use std::collections::BTreeMap;

Expand All @@ -16,9 +15,9 @@ impl<'info> Accounts<'info> for AccountInfo<'info> {
accounts: &mut &[AccountInfo<'info>],
_ix_data: &[u8],
_bumps: &mut BTreeMap<String, u8>,
) -> Result<Self, ProgramError> {
) -> AnchorResult<Self> {
if accounts.is_empty() {
return Err(ErrorCode::AccountNotEnoughKeys.into());
return anchor_attribute_error::error!(ErrorCode::AccountNotEnoughKeys);
}
let account = &accounts[0];
*accounts = &accounts[1..];
Expand Down
Loading