From e8f86b73e03cd7254ab4de1c33bc9a479e580bd5 Mon Sep 17 00:00:00 2001 From: Matthew Callens Date: Tue, 15 Mar 2022 12:57:21 -0400 Subject: [PATCH 1/6] lang: add additional `require_x` comparison macros --- lang/src/lib.rs | 155 +------------------------- lang/src/macros.rs | 263 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 267 insertions(+), 151 deletions(-) create mode 100644 lang/src/macros.rs diff --git a/lang/src/lib.rs b/lang/src/lib.rs index c3ac949332..40435fec46 100644 --- a/lang/src/lib.rs +++ b/lang/src/lib.rs @@ -40,6 +40,7 @@ mod ctor; pub mod error; #[doc(hidden)] pub mod idl; +mod macros; mod system_program; pub use crate::system_program::System; @@ -239,9 +240,9 @@ pub mod prelude { accounts::signer::Signer, accounts::system_account::SystemAccount, accounts::sysvar::Sysvar, accounts::unchecked_account::UncheckedAccount, constant, context::Context, context::CpiContext, declare_id, emit, err, error, event, interface, - program, require, require_eq, require_keys_eq, - solana_program::bpf_loader_upgradeable::UpgradeableLoaderState, source, state, zero_copy, - AccountDeserialize, AccountSerialize, Accounts, AccountsExit, AnchorDeserialize, + program, require, require_eq, require_gt, require_gte, require_keys_eq, require_keys_neq, + require_neq, solana_program::bpf_loader_upgradeable::UpgradeableLoaderState, source, state, + zero_copy, AccountDeserialize, AccountSerialize, Accounts, AccountsExit, AnchorDeserialize, AnchorSerialize, Id, Key, Owner, ProgramData, Result, System, ToAccountInfo, ToAccountInfos, ToAccountMetas, }; @@ -317,151 +318,3 @@ pub mod __private { #[doc(hidden)] pub use crate::accounts::state::PROGRAM_STATE_SEED; } - -/// Ensures a condition is true, otherwise returns with the given error. -/// Use this with or without a custom error type. -/// -/// # Example -/// ```ignore -/// // Instruction function -/// pub fn set_data(ctx: Context, data: u64) -> Result<()> { -/// require!(ctx.accounts.data.mutation_allowed, MyError::MutationForbidden); -/// ctx.accounts.data.data = data; -/// Ok(()) -/// } -/// -/// // An enum for custom error codes -/// #[error_code] -/// pub enum MyError { -/// MutationForbidden -/// } -/// -/// // An account definition -/// #[account] -/// #[derive(Default)] -/// pub struct MyData { -/// mutation_allowed: bool, -/// data: u64 -/// } -/// -/// // An account validation struct -/// #[derive(Accounts)] -/// pub struct SetData<'info> { -/// #[account(mut)] -/// pub data: Account<'info, MyData> -/// } -/// ``` -#[macro_export] -macro_rules! require { - ($invariant:expr, $error:tt $(,)?) => { - if !($invariant) { - return Err(anchor_lang::anchor_attribute_error::error!( - crate::ErrorCode::$error - )); - } - }; - ($invariant:expr, $error:expr $(,)?) => { - if !($invariant) { - return Err(anchor_lang::anchor_attribute_error::error!($error)); - } - }; -} - -/// Ensures two NON-PUBKEY values are equal. -/// -/// Use [require_keys_eq](crate::prelude::require_keys_eq) -/// to compare two pubkeys. -/// -/// Can be used with or without a custom error code. -/// -/// # Example -/// ```rust,ignore -/// pub fn set_data(ctx: Context, data: u64) -> Result<()> { -/// require_eq!(ctx.accounts.data.data, 0); -/// ctx.accounts.data.data = data; -/// Ok(()) -/// } -/// ``` -#[macro_export] -macro_rules! require_eq { - ($value1: expr, $value2: expr, $error_code:expr $(,)?) => { - if $value1 != $value2 { - return Err(error!($error_code).with_values(($value1, $value2))); - } - }; - ($value1: expr, $value2: expr $(,)?) => { - if $value1 != $value2 { - return Err(error!(anchor_lang::error::ErrorCode::RequireEqViolated) - .with_values(($value1, $value2))); - } - }; -} - -/// Ensures two pubkeys values are equal. -/// -/// Use [require_eq](crate::prelude::require_eq) -/// to compare two non-pubkey values. -/// -/// Can be used with or without a custom error code. -/// -/// # Example -/// ```rust,ignore -/// pub fn set_data(ctx: Context, data: u64) -> Result<()> { -/// require_keys_eq!(ctx.accounts.data.authority.key(), ctx.accounts.authority.key()); -/// ctx.accounts.data.data = data; -/// Ok(()) -/// } -/// ``` -#[macro_export] -macro_rules! require_keys_eq { - ($value1: expr, $value2: expr, $error_code:expr $(,)?) => { - if $value1 != $value2 { - return Err(error!($error_code).with_pubkeys(($value1, $value2))); - } - }; - ($value1: expr, $value2: expr $(,)?) => { - if $value1 != $value2 { - return Err(error!(anchor_lang::error::ErrorCode::RequireKeysEqViolated) - .with_pubkeys(($value1, $value2))); - } - }; -} - -/// Returns with the given error. -/// Use this with a custom error type. -/// -/// # Example -/// ```ignore -/// // Instruction function -/// pub fn example(ctx: Context) -> Result<()> { -/// err!(MyError::SomeError) -/// } -/// -/// // An enum for custom error codes -/// #[error_code] -/// pub enum MyError { -/// SomeError -/// } -/// ``` -#[macro_export] -macro_rules! err { - ($error:tt $(,)?) => { - Err(anchor_lang::anchor_attribute_error::error!( - crate::ErrorCode::$error - )) - }; - ($error:expr $(,)?) => { - Err(anchor_lang::anchor_attribute_error::error!($error)) - }; -} - -/// Creates a [`Source`](crate::error::Source) -#[macro_export] -macro_rules! source { - () => { - anchor_lang::error::Source { - filename: file!(), - line: line!(), - } - }; -} diff --git a/lang/src/macros.rs b/lang/src/macros.rs new file mode 100644 index 0000000000..2607faecd5 --- /dev/null +++ b/lang/src/macros.rs @@ -0,0 +1,263 @@ +/// Ensures a condition is true, otherwise returns with the given error. +/// Use this with or without a custom error type. +/// +/// # Example +/// ```ignore +/// // Instruction function +/// pub fn set_data(ctx: Context, data: u64) -> Result<()> { +/// require!(ctx.accounts.data.mutation_allowed, MyError::MutationForbidden); +/// ctx.accounts.data.data = data; +/// Ok(()) +/// } +/// +/// // An enum for custom error codes +/// #[error_code] +/// pub enum MyError { +/// MutationForbidden +/// } +/// +/// // An account definition +/// #[account] +/// #[derive(Default)] +/// pub struct MyData { +/// mutation_allowed: bool, +/// data: u64 +/// } +/// +/// // An account validation struct +/// #[derive(Accounts)] +/// pub struct SetData<'info> { +/// #[account(mut)] +/// pub data: Account<'info, MyData> +/// } +/// ``` +#[macro_export] +macro_rules! require { + ($invariant:expr, $error:tt $(,)?) => { + if !($invariant) { + return Err(anchor_lang::anchor_attribute_error::error!( + crate::ErrorCode::$error + )); + } + }; + ($invariant:expr, $error:expr $(,)?) => { + if !($invariant) { + return Err(anchor_lang::anchor_attribute_error::error!($error)); + } + }; +} + +/// Ensures two NON-PUBKEY values are equal. +/// +/// Use [require_keys_eq](crate::prelude::require_keys_eq) +/// to compare two pubkeys. +/// +/// Can be used with or without a custom error code. +/// +/// # Example +/// ```rust,ignore +/// pub fn set_data(ctx: Context, data: u64) -> Result<()> { +/// require_eq!(ctx.accounts.data.data, 0); +/// ctx.accounts.data.data = data; +/// Ok(()) +/// } +/// ``` +#[macro_export] +macro_rules! require_eq { + ($value1: expr, $value2: expr, $error_code:expr $(,)?) => { + if $value1 != $value2 { + return Err(error!($error_code).with_values(($value1, $value2))); + } + }; + ($value1: expr, $value2: expr $(,)?) => { + if $value1 != $value2 { + return Err(error!(anchor_lang::error::ErrorCode::RequireEqViolated) + .with_values(($value1, $value2))); + } + }; +} + +/// Ensures two NON-PUBKEY values are not equal. +/// +/// Use [require_keys_neq](crate::prelude::require_keys_neq) +/// to compare two pubkeys. +/// +/// Can be used with or without a custom error code. +/// +/// # Example +/// ```rust,ignore +/// pub fn set_data(ctx: Context, data: u64) -> Result<()> { +/// require_neq!(ctx.accounts.data.data, 0); +/// ctx.accounts.data.data = data; +/// Ok(()); +/// } +/// ``` +#[macro_export] +macro_rules! require_neq { + ($value1: expr, $value2: expr, $error_code: expr $(,)?) => { + if $value1 == $value2 { + return Err(error!($error_code).with_values(($value1, $value2))); + } + }; + ($value1: expr, $value2: expr $(,)?) => { + if $value1 == $value2 { + return Err(error!(anchor_lang::error::ErrorCode::RequireEqViolated) + .with_values(($value1, $value2))); + } + }; +} + +/// Ensures two pubkeys values are equal. +/// +/// Use [require_eq](crate::prelude::require_eq) +/// to compare two non-pubkey values. +/// +/// Can be used with or without a custom error code. +/// +/// # Example +/// ```rust,ignore +/// pub fn set_data(ctx: Context, data: u64) -> Result<()> { +/// require_keys_eq!(ctx.accounts.data.authority.key(), ctx.accounts.authority.key()); +/// ctx.accounts.data.data = data; +/// Ok(()) +/// } +/// ``` +#[macro_export] +macro_rules! require_keys_eq { + ($value1: expr, $value2: expr, $error_code:expr $(,)?) => { + if $value1 != $value2 { + return Err(error!($error_code).with_pubkeys(($value1, $value2))); + } + }; + ($value1: expr, $value2: expr $(,)?) => { + if $value1 != $value2 { + return Err(error!(anchor_lang::error::ErrorCode::RequireKeysEqViolated) + .with_pubkeys(($value1, $value2))); + } + }; +} + +/// Ensures two pubkeys values are not equal. +/// +/// Use [require_neq](crate::prelude::require_neq) +/// to compare two non-pubkey values. +/// +/// Can be used with or without a custom error code. +/// +/// # Example +/// ```rust,ignore +/// pub fn set_data(ctx: Context, data: u64) -> Result<()> { +/// require_keys_neq!(ctx.accounts.data.authority.key(), ctx.accounts.other.key()); +/// ctx.accounts.data.data = data; +/// Ok(()) +/// } +/// ``` +#[macro_export] +macro_rules! require_keys_neq { + ($value1: expr, $value2: expr, $error_code: expr $(,)?) => { + if $value1 == $value2 { + return Err(error!($error_code).with_pubkeys(($value1, $value2))); + } + }; + ($value1: expr, $value2: expr $(,)?) => { + if $value1 == $value2 { + return Err(error!(anchor_lang::error::ErrorCode::RequireKeysEqViolated) + .with_pubkeys(($value1, $value2))); + } + }; +} + +/// Ensures the first NON-PUBKEY value is greater than the second +/// NON-PUBKEY value. +/// +/// Can be used with or without a custom error code. +/// +/// # Example +/// ```rust,ignore +/// pub fn set_data(ctx: Context, data: u64) -> Result<()> { +/// require_gt!(ctx.accounts.data.data, 0); +/// ctx.accounts.data.data = data; +/// Ok(()); +/// } +/// ``` +#[macro_export] +macro_rules! require_gt { + ($value1: expr, $value2: expr, $error_code: expr $(,)?) => { + if $value1 <= $value2 { + return Err(error!($error_code).with_values(($value1, $value2))); + } + }; + ($value1: expr, $value2: expr $(,)?) => { + if $value1 <= $value2 { + return Err(error!(anchor_lang::error::ErrorCode::RequireEqViolated) + .with_values(($value1, $value2))); + } + }; +} + +/// Ensures the first NON-PUBKEY value is greater than or equal +/// to the second NON-PUBKEY value. +/// +/// Can be used with or without a custom error code. +/// +/// # Example +/// ```rust,ignore +/// pub fn set_data(ctx: Context, data: u64) -> Result<()> { +/// require_gte!(ctx.accounts.data.data, 1); +/// ctx.accounts.data.data = data; +/// Ok(()); +/// } +/// ``` +#[macro_export] +macro_rules! require_gte { + ($value1: expr, $value2: expr, $error_code: expr $(,)?) => { + if $value1 < $value2 { + return Err(error!($error_code).with_values(($value1, $value2))); + } + }; + ($value1: expr, $value2: expr $(,)?) => { + if $value1 < $value2 { + return Err(error!(anchor_lang::error::ErrorCode::RequireEqViolated) + .with_values(($value1, $value2))); + } + }; +} + +/// Returns with the given error. +/// Use this with a custom error type. +/// +/// # Example +/// ```ignore +/// // Instruction function +/// pub fn example(ctx: Context) -> Result<()> { +/// err!(MyError::SomeError) +/// } +/// +/// // An enum for custom error codes +/// #[error_code] +/// pub enum MyError { +/// SomeError +/// } +/// ``` +#[macro_export] +macro_rules! err { + ($error:tt $(,)?) => { + Err(anchor_lang::anchor_attribute_error::error!( + crate::ErrorCode::$error + )) + }; + ($error:expr $(,)?) => { + Err(anchor_lang::anchor_attribute_error::error!($error)) + }; +} + +/// Creates a [`Source`](crate::error::Source) +#[macro_export] +macro_rules! source { + () => { + anchor_lang::error::Source { + filename: file!(), + line: line!(), + } + }; +} From b4062683f37996bde7fcd49acfec094f77bc25e4 Mon Sep 17 00:00:00 2001 From: Matthew Callens Date: Tue, 15 Mar 2022 13:01:43 -0400 Subject: [PATCH 2/6] update changelog --- CHANGELOG.md | 5 +- lang/src/lib.rs | 265 ++++++++++++++++++++++++++++++++++++++++++++- lang/src/macros.rs | 263 -------------------------------------------- 3 files changed, 267 insertions(+), 266 deletions(-) delete mode 100644 lang/src/macros.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index c89baf7172..b7db388f73 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,12 +15,13 @@ incremented for features. * cli: Add `anchor clean` command that's the same as `cargo clean` but preserves keypairs inside `target/deploy` ([#1470](https://github.com/project-serum/anchor/issues/1470)). * cli: Running `anchor init` now initializes a new git repository for the workspace. This can be disabled with the `--no-git` flag ([#1605](https://github.com/project-serum/anchor/pull/1605)). +* cli: Add support for `anchor idl fetch` to work outside anchor workspace ([#1509](https://github.com/project-serum/anchor/pull/1509)). +* cli: [[test.validator.clone]] also clones the program data account of programs owned by the bpf upgradeable loader ([#1481](https://github.com/project-serum/anchor/issues/1481)). * lang: Add new `AccountSysvarMismatch` error code and test cases for sysvars ([#1535](https://github.com/project-serum/anchor/pull/1535)). * lang: Replace `std::io::Cursor` with a custom `Write` impl that uses the Solana mem syscalls ([#1589](https://github.com/project-serum/anchor/pull/1589)). +* lang: Add `require_neq`, `require_keys_neq`, `require_gt`, and `require_gte` comparison macros ([#1622](https://github.com/project-serum/anchor/pull/1622)). * spl: Add support for revoke instruction ([#1493](https://github.com/project-serum/anchor/pull/1493)). -* cli: Add support for `anchor idl fetch` to work outside anchor workspace ([#1509](https://github.com/project-serum/anchor/pull/1509)). * ts: Add provider parameter to `Spl.token` factory method ([#1597](https://github.com/project-serum/anchor/pull/1597)). -* cli: [[test.validator.clone]] also clones the program data account of programs owned by the bpf upgradeable loader ([#1481](https://github.com/project-serum/anchor/issues/1481)). ### Fixes diff --git a/lang/src/lib.rs b/lang/src/lib.rs index 40435fec46..0a50f048f5 100644 --- a/lang/src/lib.rs +++ b/lang/src/lib.rs @@ -40,7 +40,6 @@ mod ctor; pub mod error; #[doc(hidden)] pub mod idl; -mod macros; mod system_program; pub use crate::system_program::System; @@ -318,3 +317,267 @@ pub mod __private { #[doc(hidden)] pub use crate::accounts::state::PROGRAM_STATE_SEED; } + +/// Ensures a condition is true, otherwise returns with the given error. +/// Use this with or without a custom error type. +/// +/// # Example +/// ```ignore +/// // Instruction function +/// pub fn set_data(ctx: Context, data: u64) -> Result<()> { +/// require!(ctx.accounts.data.mutation_allowed, MyError::MutationForbidden); +/// ctx.accounts.data.data = data; +/// Ok(()) +/// } +/// +/// // An enum for custom error codes +/// #[error_code] +/// pub enum MyError { +/// MutationForbidden +/// } +/// +/// // An account definition +/// #[account] +/// #[derive(Default)] +/// pub struct MyData { +/// mutation_allowed: bool, +/// data: u64 +/// } +/// +/// // An account validation struct +/// #[derive(Accounts)] +/// pub struct SetData<'info> { +/// #[account(mut)] +/// pub data: Account<'info, MyData> +/// } +/// ``` +#[macro_export] +macro_rules! require { + ($invariant:expr, $error:tt $(,)?) => { + if !($invariant) { + return Err(anchor_lang::anchor_attribute_error::error!( + crate::ErrorCode::$error + )); + } + }; + ($invariant:expr, $error:expr $(,)?) => { + if !($invariant) { + return Err(anchor_lang::anchor_attribute_error::error!($error)); + } + }; +} + +/// Ensures two NON-PUBKEY values are equal. +/// +/// Use [require_keys_eq](crate::prelude::require_keys_eq) +/// to compare two pubkeys. +/// +/// Can be used with or without a custom error code. +/// +/// # Example +/// ```rust,ignore +/// pub fn set_data(ctx: Context, data: u64) -> Result<()> { +/// require_eq!(ctx.accounts.data.data, 0); +/// ctx.accounts.data.data = data; +/// Ok(()) +/// } +/// ``` +#[macro_export] +macro_rules! require_eq { + ($value1: expr, $value2: expr, $error_code:expr $(,)?) => { + if $value1 != $value2 { + return Err(error!($error_code).with_values(($value1, $value2))); + } + }; + ($value1: expr, $value2: expr $(,)?) => { + if $value1 != $value2 { + return Err(error!(anchor_lang::error::ErrorCode::RequireEqViolated) + .with_values(($value1, $value2))); + } + }; +} + +/// Ensures two NON-PUBKEY values are not equal. +/// +/// Use [require_keys_neq](crate::prelude::require_keys_neq) +/// to compare two pubkeys. +/// +/// Can be used with or without a custom error code. +/// +/// # Example +/// ```rust,ignore +/// pub fn set_data(ctx: Context, data: u64) -> Result<()> { +/// require_neq!(ctx.accounts.data.data, 0); +/// ctx.accounts.data.data = data; +/// Ok(()); +/// } +/// ``` +#[macro_export] +macro_rules! require_neq { + ($value1: expr, $value2: expr, $error_code: expr $(,)?) => { + if $value1 == $value2 { + return Err(error!($error_code).with_values(($value1, $value2))); + } + }; + ($value1: expr, $value2: expr $(,)?) => { + if $value1 == $value2 { + return Err(error!(anchor_lang::error::ErrorCode::RequireEqViolated) + .with_values(($value1, $value2))); + } + }; +} + +/// Ensures two pubkeys values are equal. +/// +/// Use [require_eq](crate::prelude::require_eq) +/// to compare two non-pubkey values. +/// +/// Can be used with or without a custom error code. +/// +/// # Example +/// ```rust,ignore +/// pub fn set_data(ctx: Context, data: u64) -> Result<()> { +/// require_keys_eq!(ctx.accounts.data.authority.key(), ctx.accounts.authority.key()); +/// ctx.accounts.data.data = data; +/// Ok(()) +/// } +/// ``` +#[macro_export] +macro_rules! require_keys_eq { + ($value1: expr, $value2: expr, $error_code:expr $(,)?) => { + if $value1 != $value2 { + return Err(error!($error_code).with_pubkeys(($value1, $value2))); + } + }; + ($value1: expr, $value2: expr $(,)?) => { + if $value1 != $value2 { + return Err(error!(anchor_lang::error::ErrorCode::RequireKeysEqViolated) + .with_pubkeys(($value1, $value2))); + } + }; +} + +/// Ensures two pubkeys values are not equal. +/// +/// Use [require_neq](crate::prelude::require_neq) +/// to compare two non-pubkey values. +/// +/// Can be used with or without a custom error code. +/// +/// # Example +/// ```rust,ignore +/// pub fn set_data(ctx: Context, data: u64) -> Result<()> { +/// require_keys_neq!(ctx.accounts.data.authority.key(), ctx.accounts.other.key()); +/// ctx.accounts.data.data = data; +/// Ok(()) +/// } +/// ``` +#[macro_export] +macro_rules! require_keys_neq { + ($value1: expr, $value2: expr, $error_code: expr $(,)?) => { + if $value1 == $value2 { + return Err(error!($error_code).with_pubkeys(($value1, $value2))); + } + }; + ($value1: expr, $value2: expr $(,)?) => { + if $value1 == $value2 { + return Err(error!(anchor_lang::error::ErrorCode::RequireKeysEqViolated) + .with_pubkeys(($value1, $value2))); + } + }; +} + +/// Ensures the first NON-PUBKEY value is greater than the second +/// NON-PUBKEY value. +/// +/// Can be used with or without a custom error code. +/// +/// # Example +/// ```rust,ignore +/// pub fn set_data(ctx: Context, data: u64) -> Result<()> { +/// require_gt!(ctx.accounts.data.data, 0); +/// ctx.accounts.data.data = data; +/// Ok(()); +/// } +/// ``` +#[macro_export] +macro_rules! require_gt { + ($value1: expr, $value2: expr, $error_code: expr $(,)?) => { + if $value1 <= $value2 { + return Err(error!($error_code).with_values(($value1, $value2))); + } + }; + ($value1: expr, $value2: expr $(,)?) => { + if $value1 <= $value2 { + return Err(error!(anchor_lang::error::ErrorCode::RequireEqViolated) + .with_values(($value1, $value2))); + } + }; +} + +/// Ensures the first NON-PUBKEY value is greater than or equal +/// to the second NON-PUBKEY value. +/// +/// Can be used with or without a custom error code. +/// +/// # Example +/// ```rust,ignore +/// pub fn set_data(ctx: Context, data: u64) -> Result<()> { +/// require_gte!(ctx.accounts.data.data, 1); +/// ctx.accounts.data.data = data; +/// Ok(()); +/// } +/// ``` +#[macro_export] +macro_rules! require_gte { + ($value1: expr, $value2: expr, $error_code: expr $(,)?) => { + if $value1 < $value2 { + return Err(error!($error_code).with_values(($value1, $value2))); + } + }; + ($value1: expr, $value2: expr $(,)?) => { + if $value1 < $value2 { + return Err(error!(anchor_lang::error::ErrorCode::RequireEqViolated) + .with_values(($value1, $value2))); + } + }; +} + +/// Returns with the given error. +/// Use this with a custom error type. +/// +/// # Example +/// ```ignore +/// // Instruction function +/// pub fn example(ctx: Context) -> Result<()> { +/// err!(MyError::SomeError) +/// } +/// +/// // An enum for custom error codes +/// #[error_code] +/// pub enum MyError { +/// SomeError +/// } +/// ``` +#[macro_export] +macro_rules! err { + ($error:tt $(,)?) => { + Err(anchor_lang::anchor_attribute_error::error!( + crate::ErrorCode::$error + )) + }; + ($error:expr $(,)?) => { + Err(anchor_lang::anchor_attribute_error::error!($error)) + }; +} + +/// Creates a [`Source`](crate::error::Source) +#[macro_export] +macro_rules! source { + () => { + anchor_lang::error::Source { + filename: file!(), + line: line!(), + } + }; +} diff --git a/lang/src/macros.rs b/lang/src/macros.rs deleted file mode 100644 index 2607faecd5..0000000000 --- a/lang/src/macros.rs +++ /dev/null @@ -1,263 +0,0 @@ -/// Ensures a condition is true, otherwise returns with the given error. -/// Use this with or without a custom error type. -/// -/// # Example -/// ```ignore -/// // Instruction function -/// pub fn set_data(ctx: Context, data: u64) -> Result<()> { -/// require!(ctx.accounts.data.mutation_allowed, MyError::MutationForbidden); -/// ctx.accounts.data.data = data; -/// Ok(()) -/// } -/// -/// // An enum for custom error codes -/// #[error_code] -/// pub enum MyError { -/// MutationForbidden -/// } -/// -/// // An account definition -/// #[account] -/// #[derive(Default)] -/// pub struct MyData { -/// mutation_allowed: bool, -/// data: u64 -/// } -/// -/// // An account validation struct -/// #[derive(Accounts)] -/// pub struct SetData<'info> { -/// #[account(mut)] -/// pub data: Account<'info, MyData> -/// } -/// ``` -#[macro_export] -macro_rules! require { - ($invariant:expr, $error:tt $(,)?) => { - if !($invariant) { - return Err(anchor_lang::anchor_attribute_error::error!( - crate::ErrorCode::$error - )); - } - }; - ($invariant:expr, $error:expr $(,)?) => { - if !($invariant) { - return Err(anchor_lang::anchor_attribute_error::error!($error)); - } - }; -} - -/// Ensures two NON-PUBKEY values are equal. -/// -/// Use [require_keys_eq](crate::prelude::require_keys_eq) -/// to compare two pubkeys. -/// -/// Can be used with or without a custom error code. -/// -/// # Example -/// ```rust,ignore -/// pub fn set_data(ctx: Context, data: u64) -> Result<()> { -/// require_eq!(ctx.accounts.data.data, 0); -/// ctx.accounts.data.data = data; -/// Ok(()) -/// } -/// ``` -#[macro_export] -macro_rules! require_eq { - ($value1: expr, $value2: expr, $error_code:expr $(,)?) => { - if $value1 != $value2 { - return Err(error!($error_code).with_values(($value1, $value2))); - } - }; - ($value1: expr, $value2: expr $(,)?) => { - if $value1 != $value2 { - return Err(error!(anchor_lang::error::ErrorCode::RequireEqViolated) - .with_values(($value1, $value2))); - } - }; -} - -/// Ensures two NON-PUBKEY values are not equal. -/// -/// Use [require_keys_neq](crate::prelude::require_keys_neq) -/// to compare two pubkeys. -/// -/// Can be used with or without a custom error code. -/// -/// # Example -/// ```rust,ignore -/// pub fn set_data(ctx: Context, data: u64) -> Result<()> { -/// require_neq!(ctx.accounts.data.data, 0); -/// ctx.accounts.data.data = data; -/// Ok(()); -/// } -/// ``` -#[macro_export] -macro_rules! require_neq { - ($value1: expr, $value2: expr, $error_code: expr $(,)?) => { - if $value1 == $value2 { - return Err(error!($error_code).with_values(($value1, $value2))); - } - }; - ($value1: expr, $value2: expr $(,)?) => { - if $value1 == $value2 { - return Err(error!(anchor_lang::error::ErrorCode::RequireEqViolated) - .with_values(($value1, $value2))); - } - }; -} - -/// Ensures two pubkeys values are equal. -/// -/// Use [require_eq](crate::prelude::require_eq) -/// to compare two non-pubkey values. -/// -/// Can be used with or without a custom error code. -/// -/// # Example -/// ```rust,ignore -/// pub fn set_data(ctx: Context, data: u64) -> Result<()> { -/// require_keys_eq!(ctx.accounts.data.authority.key(), ctx.accounts.authority.key()); -/// ctx.accounts.data.data = data; -/// Ok(()) -/// } -/// ``` -#[macro_export] -macro_rules! require_keys_eq { - ($value1: expr, $value2: expr, $error_code:expr $(,)?) => { - if $value1 != $value2 { - return Err(error!($error_code).with_pubkeys(($value1, $value2))); - } - }; - ($value1: expr, $value2: expr $(,)?) => { - if $value1 != $value2 { - return Err(error!(anchor_lang::error::ErrorCode::RequireKeysEqViolated) - .with_pubkeys(($value1, $value2))); - } - }; -} - -/// Ensures two pubkeys values are not equal. -/// -/// Use [require_neq](crate::prelude::require_neq) -/// to compare two non-pubkey values. -/// -/// Can be used with or without a custom error code. -/// -/// # Example -/// ```rust,ignore -/// pub fn set_data(ctx: Context, data: u64) -> Result<()> { -/// require_keys_neq!(ctx.accounts.data.authority.key(), ctx.accounts.other.key()); -/// ctx.accounts.data.data = data; -/// Ok(()) -/// } -/// ``` -#[macro_export] -macro_rules! require_keys_neq { - ($value1: expr, $value2: expr, $error_code: expr $(,)?) => { - if $value1 == $value2 { - return Err(error!($error_code).with_pubkeys(($value1, $value2))); - } - }; - ($value1: expr, $value2: expr $(,)?) => { - if $value1 == $value2 { - return Err(error!(anchor_lang::error::ErrorCode::RequireKeysEqViolated) - .with_pubkeys(($value1, $value2))); - } - }; -} - -/// Ensures the first NON-PUBKEY value is greater than the second -/// NON-PUBKEY value. -/// -/// Can be used with or without a custom error code. -/// -/// # Example -/// ```rust,ignore -/// pub fn set_data(ctx: Context, data: u64) -> Result<()> { -/// require_gt!(ctx.accounts.data.data, 0); -/// ctx.accounts.data.data = data; -/// Ok(()); -/// } -/// ``` -#[macro_export] -macro_rules! require_gt { - ($value1: expr, $value2: expr, $error_code: expr $(,)?) => { - if $value1 <= $value2 { - return Err(error!($error_code).with_values(($value1, $value2))); - } - }; - ($value1: expr, $value2: expr $(,)?) => { - if $value1 <= $value2 { - return Err(error!(anchor_lang::error::ErrorCode::RequireEqViolated) - .with_values(($value1, $value2))); - } - }; -} - -/// Ensures the first NON-PUBKEY value is greater than or equal -/// to the second NON-PUBKEY value. -/// -/// Can be used with or without a custom error code. -/// -/// # Example -/// ```rust,ignore -/// pub fn set_data(ctx: Context, data: u64) -> Result<()> { -/// require_gte!(ctx.accounts.data.data, 1); -/// ctx.accounts.data.data = data; -/// Ok(()); -/// } -/// ``` -#[macro_export] -macro_rules! require_gte { - ($value1: expr, $value2: expr, $error_code: expr $(,)?) => { - if $value1 < $value2 { - return Err(error!($error_code).with_values(($value1, $value2))); - } - }; - ($value1: expr, $value2: expr $(,)?) => { - if $value1 < $value2 { - return Err(error!(anchor_lang::error::ErrorCode::RequireEqViolated) - .with_values(($value1, $value2))); - } - }; -} - -/// Returns with the given error. -/// Use this with a custom error type. -/// -/// # Example -/// ```ignore -/// // Instruction function -/// pub fn example(ctx: Context) -> Result<()> { -/// err!(MyError::SomeError) -/// } -/// -/// // An enum for custom error codes -/// #[error_code] -/// pub enum MyError { -/// SomeError -/// } -/// ``` -#[macro_export] -macro_rules! err { - ($error:tt $(,)?) => { - Err(anchor_lang::anchor_attribute_error::error!( - crate::ErrorCode::$error - )) - }; - ($error:expr $(,)?) => { - Err(anchor_lang::anchor_attribute_error::error!($error)) - }; -} - -/// Creates a [`Source`](crate::error::Source) -#[macro_export] -macro_rules! source { - () => { - anchor_lang::error::Source { - filename: file!(), - line: line!(), - } - }; -} From 01d957e4346ce3af73460f13c1b10c07867e24b0 Mon Sep 17 00:00:00 2001 From: Matthew Callens Date: Tue, 15 Mar 2022 14:06:26 -0400 Subject: [PATCH 3/6] update comment --- lang/src/lib.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lang/src/lib.rs b/lang/src/lib.rs index 0a50f048f5..5d8f159933 100644 --- a/lang/src/lib.rs +++ b/lang/src/lib.rs @@ -457,7 +457,7 @@ macro_rules! require_keys_eq { }; } -/// Ensures two pubkeys values are not equal. +/// Ensures two pubkeys are not equal. /// /// Use [require_neq](crate::prelude::require_neq) /// to compare two non-pubkey values. @@ -490,6 +490,8 @@ macro_rules! require_keys_neq { /// Ensures the first NON-PUBKEY value is greater than the second /// NON-PUBKEY value. /// +/// To include an equality check, use [require_gte](crate::require_gte). +/// /// Can be used with or without a custom error code. /// /// # Example From f6ead1c1f210b78090ae9b34e70963ed0d031c83 Mon Sep 17 00:00:00 2001 From: Matthew Callens Date: Tue, 15 Mar 2022 21:21:04 -0400 Subject: [PATCH 4/6] add new default error codes for the new require macros --- lang/src/error.rs | 12 ++++++++++++ lang/src/lib.rs | 12 +++++++----- ts/src/error.ts | 11 +++++++++++ 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/lang/src/error.rs b/lang/src/error.rs index 045884ec02..82f19f4e7e 100644 --- a/lang/src/error.rs +++ b/lang/src/error.rs @@ -116,6 +116,18 @@ pub enum ErrorCode { /// 2502 - A require_keys_eq expression was violated #[msg("A require_keys_eq expression was violated")] RequireKeysEqViolated, + /// 2503 - A require_neq expression was violated + #[msg("A require_neq expression was violated")] + RequireNeqViolated, + /// 2504 - A require_keys_neq expression was violated + #[msg("A require_keys_neq expression was violated")] + RequireKeysNeqViolated, + /// 2505 - A require_gt expression was violated + #[msg("A require_gt expression was violated")] + RequireGtViolated, + /// 2506 - A require_gte expression was violated + #[msg("A require_gte expression was violated")] + RequireGteViolated, // Accounts. /// 3000 - The account discriminator was already set on this account diff --git a/lang/src/lib.rs b/lang/src/lib.rs index 5d8f159933..89c9f96799 100644 --- a/lang/src/lib.rs +++ b/lang/src/lib.rs @@ -421,7 +421,7 @@ macro_rules! require_neq { }; ($value1: expr, $value2: expr $(,)?) => { if $value1 == $value2 { - return Err(error!(anchor_lang::error::ErrorCode::RequireEqViolated) + return Err(error!(anchor_lang::error::ErrorCode::RequireNeqViolated) .with_values(($value1, $value2))); } }; @@ -481,8 +481,10 @@ macro_rules! require_keys_neq { }; ($value1: expr, $value2: expr $(,)?) => { if $value1 == $value2 { - return Err(error!(anchor_lang::error::ErrorCode::RequireKeysEqViolated) - .with_pubkeys(($value1, $value2))); + return Err( + error!(anchor_lang::error::ErrorCode::RequireKeysNeqViolated) + .with_pubkeys(($value1, $value2)), + ); } }; } @@ -511,7 +513,7 @@ macro_rules! require_gt { }; ($value1: expr, $value2: expr $(,)?) => { if $value1 <= $value2 { - return Err(error!(anchor_lang::error::ErrorCode::RequireEqViolated) + return Err(error!(anchor_lang::error::ErrorCode::RequireGtViolated) .with_values(($value1, $value2))); } }; @@ -539,7 +541,7 @@ macro_rules! require_gte { }; ($value1: expr, $value2: expr $(,)?) => { if $value1 < $value2 { - return Err(error!(anchor_lang::error::ErrorCode::RequireEqViolated) + return Err(error!(anchor_lang::error::ErrorCode::RequireGteViolated) .with_values(($value1, $value2))); } }; diff --git a/ts/src/error.ts b/ts/src/error.ts index 0b969e5765..6d1073faf6 100644 --- a/ts/src/error.ts +++ b/ts/src/error.ts @@ -99,6 +99,10 @@ const LangErrorCode = { RequireViolated: 2500, RequireEqViolated: 2501, RequireKeysEqViolated: 2502, + RequireNeqViolated: 2503, + RequireKeysNeqViolated: 2504, + RequireGtViolated: 2505, + RequireGteViolated: 2506, // Accounts. AccountDiscriminatorAlreadySet: 3000, @@ -197,6 +201,13 @@ const LangErrorMessage = new Map([ LangErrorCode.RequireKeysEqViolated, "A require_keys_eq expression was violated", ], + [LangErrorCode.RequireNeqViolated, "A require_neq expression was violated"], + [ + LangErrorCode.RequireKeysNeqViolated, + "A require_keys_neq expression was violated", + ], + [LangErrorCode.RequireGtViolated, "A require_gt expression was violated"], + [LangErrorCode.RequireGteViolated, "A require_gte expression was violated"], // Accounts. [ From 3fee1e833dc6d9d55fd90ee7d770c1ac357e2407 Mon Sep 17 00:00:00 2001 From: Matthew Callens Date: Wed, 16 Mar 2022 08:59:35 -0400 Subject: [PATCH 5/6] add tests for new require macros --- tests/errors/Anchor.toml | 1 + tests/errors/programs/errors/src/lib.rs | 69 +++++++++++- tests/errors/tests/errors.js | 142 ++++++++++++++++++++++++ tests/yarn.lock | 93 +++++++++++++++- 4 files changed, 297 insertions(+), 8 deletions(-) diff --git a/tests/errors/Anchor.toml b/tests/errors/Anchor.toml index 82be99c67c..0127f7a967 100644 --- a/tests/errors/Anchor.toml +++ b/tests/errors/Anchor.toml @@ -9,3 +9,4 @@ errors = "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS" test = "yarn run mocha -t 1000000 tests/" [features] +seeds = false diff --git a/tests/errors/programs/errors/src/lib.rs b/tests/errors/programs/errors/src/lib.rs index d67ca0897a..edc4c755dd 100644 --- a/tests/errors/programs/errors/src/lib.rs +++ b/tests/errors/programs/errors/src/lib.rs @@ -74,8 +74,22 @@ mod errors { Ok(()) } + pub fn require_neq(_ctx: Context) -> Result<()> { + require_neq!(500, 500, MyError::ValueMatch); + Ok(()) + } + + pub fn require_neq_default_error(_ctx: Context) -> Result<()> { + require_neq!(500, 500); + Ok(()) + } + pub fn require_keys_eq(ctx: Context) -> Result<()> { - require_keys_eq!(ctx.accounts.some_account.key(), *ctx.program_id, MyError::ValueMismatch); + require_keys_eq!( + ctx.accounts.some_account.key(), + *ctx.program_id, + MyError::ValueMismatch + ); Ok(()) } @@ -83,6 +97,40 @@ mod errors { require_keys_eq!(ctx.accounts.some_account.key(), *ctx.program_id); Ok(()) } + + pub fn require_keys_neq(ctx: Context) -> Result<()> { + require_keys_neq!( + ctx.accounts.some_account.key(), + *ctx.program_id, + MyError::ValueMatch + ); + Ok(()) + } + + pub fn require_keys_neq_default_error(ctx: Context) -> Result<()> { + require_keys_neq!(ctx.accounts.some_account.key(), *ctx.program_id); + Ok(()) + } + + pub fn require_gt(_ctx: Context) -> Result<()> { + require_gt!(5, 10, MyError::ValueLessOrEqual); + Ok(()) + } + + pub fn require_gt_default_error(_ctx: Context) -> Result<()> { + require_gt!(10, 10); + Ok(()) + } + + pub fn require_gte(_ctx: Context) -> Result<()> { + require_gte!(5, 10, MyError::ValueLess); + Ok(()) + } + + pub fn require_gte_default_error(_ctx: Context) -> Result<()> { + require_gte!(5, 10); + Ok(()) + } } #[derive(Accounts)] @@ -133,9 +181,23 @@ pub struct AccountOwnedByWrongProgramError<'info> { #[derive(Accounts)] pub struct RequireEq {} +#[derive(Accounts)] +pub struct RequireNeq {} + +#[derive(Accounts)] +pub struct RequireGt {} + +#[derive(Accounts)] +pub struct RequireGte {} + #[derive(Accounts)] pub struct RequireKeysEq<'info> { - pub some_account: UncheckedAccount<'info> + pub some_account: UncheckedAccount<'info>, +} + +#[derive(Accounts)] +pub struct RequireKeysNeq<'info> { + pub some_account: UncheckedAccount<'info>, } #[error_code] @@ -146,4 +208,7 @@ pub enum MyError { HelloNext, HelloCustom, ValueMismatch, + ValueMatch, + ValueLess, + ValueLessOrEqual, } diff --git a/tests/errors/tests/errors.js b/tests/errors/tests/errors.js index 0313562cff..2af373fa91 100644 --- a/tests/errors/tests/errors.js +++ b/tests/errors/tests/errors.js @@ -333,6 +333,40 @@ describe("errors", () => { ]); }); + it("Emits a ValueMatch error via require_neq", async () => { + await withLogTest(async () => { + try { + const tx = await program.rpc.requireNeq(); + assert.fail( + "Unexpected success in creating a transaction that should have failed with `ValueMatch` error" + ); + } catch (err) { + assert.equal(err.code, 6127); + } + }, [ + "Program log: AnchorError thrown in programs/errors/src/lib.rs:78. Error Code: ValueMatch. Error Number: 6127. Error Message: ValueMatch.", + "Program log: Left: 500", + "Program log: Right: 500", + ]); + }); + + it('Emits a RequireNeqViolated error via require_neq', async () => { + await withLogTest(async () => { + try { + const tx = await program.rpc.requireNeqDefaultError(); + assert.fail( + "Unexpected success in creating a transaction that should have failed with `RequireNeqViolated` error" + ); + } catch (err) { + assert.equal(err.code, 2503); + } + }, [ + "Program log: AnchorError thrown in programs/errors/src/lib.rs:83. Error Code: RequireNeqViolated. Error Number: 2503. Error Message: A require_neq expression was violated.", + "Program log: Left: 500", + "Program log: Right: 500", + ]); + }) + it("Emits a ValueMismatch error via require_keys_eq", async () => { const someAccount = anchor.web3.Keypair.generate().publicKey; await withLogTest(async () => { @@ -380,4 +414,112 @@ describe("errors", () => { `Program log: ${program.programId}`, ]); }); + + it("Emits a ValueMatch error via require_keys_neq", async () => { + await withLogTest(async () => { + const someAccount = program.programId + try { + const tx = await program.rpc.requireKeysNeq({ + accounts: { + someAccount, + }, + }); + assert.fail( + "Unexpected success in creating a transaction that should have failed with `ValueMatch` error" + ); + } catch (err) { + assert.equal(err.code, 6127); + } + }, [ + "Program log: AnchorError thrown in programs/errors/src/lib.rs:102. Error Code: ValueMatch. Error Number: 6127. Error Message: ValueMatch.", + "Program log: Left:", + `Program log: ${someAccount}`, + "Program log: Right:", + `Program log: ${program.programId}`, + ]); + }); + + it("Emits a RequireKeysNeqViolated error via require_keys_neq", async () => { + const someAccount = program.programId; + await withLogTest(async () => { + try { + const tx = await program.rpc.requireKeysNeqDefaultError({ + accounts: { + someAccount, + }, + }); + assert.fail( + "Unexpected success in creating a transaction that should have failed with `RequireKeysNeqViolated` error" + ); + } catch (err) { + assert.equal(err.code, 2504); + } + }, [ + "Program log: AnchorError thrown in programs/errors/src/lib.rs:111. Error Code: RequireKeysNeqViolated. Error Number: 2504. Error Message: A require_keys_neq expression was violated.", + "Program log: Left:", + `Program log: ${someAccount}`, + "Program log: Right:", + `Program log: ${program.programId}`, + ]); + }); + + it('Emits a ValueLessOrEqual error via require_gt', async () => { + await withLogTest(async () => { + try { + const tx = await program.rpc.requireGt() + assert.fail("Unexpected success in creating a transaction that should have failed with `ValueLessOrEqual` error") + } catch (err) { + assert.equal(err.code, 6129) + } + }, [ + "Program log: AnchorError thrown in programs/errors/src/lib.rs:116. Error Code: ValueLessOrEqual. Error Number: 6129. Error Message: ValueLessOrEqual.", + "Program log: Left: 5", + "Program log: Right: 10", + ]) + }) + + it('Emits a RequireGtViolated error via require_gt', async () => { + await withLogTest(async () => { + try { + const tx = await program.rpc.requireGtDefaultError() + assert.fail("Unexpected success in creating a transaction that should have failed with `RequireGtViolated` error") + } catch (err) { + assert.equal(err.code, 2505) + } + }, [ + "Program log: AnchorError thrown in programs/errors/src/lib.rs:121. Error Code: RequireGtViolated. Error Number: 2505. Error Message: A require_gt expression was violated.", + "Program log: Left: 10", + "Program log: Right: 10", + ]) + }) + + it('Emits a ValueLess error via require_gte', async () => { + await withLogTest(async () => { + try { + const tx = await program.rpc.requireGte() + assert.fail("Unexpected success in creating a transaction that should have failed with `ValueLess` error") + } catch (err) { + assert.equal(err.code, 6128) + } + }, [ + "Program log: AnchorError thrown in programs/errors/src/lib.rs:126. Error Code: ValueLess. Error Number: 6128. Error Message: ValueLess.", + "Program log: Left: 5", + "Program log: Right: 10", + ]) + }) + + it('Emits a RequireGteViolated error via require_gte', async () => { + await withLogTest(async () => { + try { + const tx = await program.rpc.requireGteDefaultError() + assert.fail("Unexpected success in creating a transaction that should have failed with `RequireGteViolated` error") + } catch (err) { + assert.equal(err.code, 2506) + } + }, [ + "Program log: AnchorError thrown in programs/errors/src/lib.rs:131. Error Code: RequireGteViolated. Error Number: 2506. Error Message: A require_gte expression was violated.", + "Program log: Left: 5", + "Program log: Right: 10", + ]) + }) }); diff --git a/tests/yarn.lock b/tests/yarn.lock index 14e85c6443..edafef057d 100644 --- a/tests/yarn.lock +++ b/tests/yarn.lock @@ -50,12 +50,12 @@ snake-case "^3.0.4" toml "^3.0.0" -"@project-serum/anchor@^0.21.0": - version "0.21.0" - resolved "https://registry.yarnpkg.com/@project-serum/anchor/-/anchor-0.21.0.tgz#ad5fb33744991ec1900cdb2fd22707c908b12b5f" - integrity sha512-flRuW/F+iC8mitNokx82LOXyND7Dyk6n5UUPJpQv/+NfySFrNFlzuQZaBZJ4CG5g9s8HS/uaaIz1nVkDR8V/QA== +"@project-serum/anchor@^0.22.1": + version "0.22.1" + resolved "https://registry.yarnpkg.com/@project-serum/anchor/-/anchor-0.22.1.tgz#698a9620f94691de0a12bbc650a5c8380e2f0e8a" + integrity sha512-5pHeyvQhzLahIQ8aZymmDMZJAJFklN0joZdI+YIqFkK2uU/mlKr6rBLQjxysf/j1mLLiNG00tdyLfUtTAdQz7w== dependencies: - "@project-serum/borsh" "^0.2.4" + "@project-serum/borsh" "^0.2.5" "@solana/web3.js" "^1.17.0" base64-js "^1.5.1" bn.js "^5.1.2" @@ -79,7 +79,7 @@ bn.js "^5.1.2" buffer-layout "^1.2.0" -"@project-serum/borsh@^0.2.4": +"@project-serum/borsh@^0.2.5": version "0.2.5" resolved "https://registry.yarnpkg.com/@project-serum/borsh/-/borsh-0.2.5.tgz#6059287aa624ecebbfc0edd35e4c28ff987d8663" integrity sha512-UmeUkUoKdQ7rhx6Leve1SssMR/Ghv8qrEiyywyxSWg7ooV7StdpPBhciiy5eB3T0qU1BXvdRNC8TdrkxK7WC5Q== @@ -421,6 +421,21 @@ chokidar@3.5.2: optionalDependencies: fsevents "~2.3.2" +chokidar@3.5.3: + version "3.5.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + circular-json@^0.5.9: version "0.5.9" resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.5.9.tgz#932763ae88f4f7dead7a0d09c8a51a4743a53b1d" @@ -483,6 +498,13 @@ debug@4.3.2: dependencies: ms "2.1.2" +debug@4.3.3: + version "4.3.3" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" + integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== + dependencies: + ms "2.1.2" + decamelize@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" @@ -639,6 +661,18 @@ glob@7.1.7: once "^1.3.0" path-is-absolute "^1.0.0" +glob@7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" + integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + growl@1.10.5: version "1.10.5" resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" @@ -847,6 +881,13 @@ minimatch@3.0.4, minimatch@^3.0.4: dependencies: brace-expansion "^1.1.7" +minimatch@4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-4.2.1.tgz#40d9d511a46bdc4e563c22c3080cde9c0d8299b4" + integrity sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g== + dependencies: + brace-expansion "^1.1.7" + minimist@^1.2.0, minimist@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" @@ -889,6 +930,36 @@ mocha@^9.1.3: yargs-parser "20.2.4" yargs-unparser "2.0.0" +mocha@^9.2.2: + version "9.2.2" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-9.2.2.tgz#d70db46bdb93ca57402c809333e5a84977a88fb9" + integrity sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g== + dependencies: + "@ungap/promise-all-settled" "1.1.2" + ansi-colors "4.1.1" + browser-stdout "1.3.1" + chokidar "3.5.3" + debug "4.3.3" + diff "5.0.0" + escape-string-regexp "4.0.0" + find-up "5.0.0" + glob "7.2.0" + growl "1.10.5" + he "1.2.0" + js-yaml "4.1.0" + log-symbols "4.1.0" + minimatch "4.2.1" + ms "2.1.3" + nanoid "3.3.1" + serialize-javascript "6.0.0" + strip-json-comments "3.1.1" + supports-color "8.1.1" + which "2.0.2" + workerpool "6.2.0" + yargs "16.2.0" + yargs-parser "20.2.4" + yargs-unparser "2.0.0" + ms@2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" @@ -904,6 +975,11 @@ nanoid@3.1.25: resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.25.tgz#09ca32747c0e543f0e1814b7d3793477f9c8e152" integrity sha512-rdwtIXaXCLFAQbnfqDRnI6jaRHp9fTcYBjtFKE8eezcZ7LuLjhUaQGNeMXf1HmRoCH32CLz6XwX0TtxEOS/A3Q== +nanoid@3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.1.tgz#6347a18cac88af88f58af0b3594b723d5e99bb35" + integrity sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw== + no-case@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d" @@ -1255,6 +1331,11 @@ workerpool@6.1.5: resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.1.5.tgz#0f7cf076b6215fd7e1da903ff6f22ddd1886b581" integrity sha512-XdKkCK0Zqc6w3iTxLckiuJ81tiD/o5rBE/m+nXpRCB+/Sq4DqkfXZ/x0jW02DG1tGsfUGXbTJyZDP+eu67haSw== +workerpool@6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.0.tgz#827d93c9ba23ee2019c3ffaff5c27fccea289e8b" + integrity sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A== + wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" From a3b816a479695bed8975bce4d79a3cc1cd375622 Mon Sep 17 00:00:00 2001 From: Matthew Callens Date: Wed, 16 Mar 2022 11:36:24 -0400 Subject: [PATCH 6/6] fix formatting and tests --- tests/errors/tests/errors.js | 66 ++++++++++++++++++++---------------- 1 file changed, 37 insertions(+), 29 deletions(-) diff --git a/tests/errors/tests/errors.js b/tests/errors/tests/errors.js index 2af373fa91..cbb28a3a5f 100644 --- a/tests/errors/tests/errors.js +++ b/tests/errors/tests/errors.js @@ -350,7 +350,7 @@ describe("errors", () => { ]); }); - it('Emits a RequireNeqViolated error via require_neq', async () => { + it("Emits a RequireNeqViolated error via require_neq", async () => { await withLogTest(async () => { try { const tx = await program.rpc.requireNeqDefaultError(); @@ -365,7 +365,7 @@ describe("errors", () => { "Program log: Left: 500", "Program log: Right: 500", ]); - }) + }); it("Emits a ValueMismatch error via require_keys_eq", async () => { const someAccount = anchor.web3.Keypair.generate().publicKey; @@ -383,7 +383,7 @@ describe("errors", () => { assert.equal(err.code, 6126); } }, [ - "Program log: AnchorError thrown in programs/errors/src/lib.rs:78. Error Code: ValueMismatch. Error Number: 6126. Error Message: ValueMismatch.", + "Program log: AnchorError thrown in programs/errors/src/lib.rs:88. Error Code: ValueMismatch. Error Number: 6126. Error Message: ValueMismatch.", "Program log: Left:", `Program log: ${someAccount}`, "Program log: Right:", @@ -407,7 +407,7 @@ describe("errors", () => { assert.equal(err.code, 2502); } }, [ - "Program log: AnchorError thrown in programs/errors/src/lib.rs:83. Error Code: RequireKeysEqViolated. Error Number: 2502. Error Message: A require_keys_eq expression was violated.", + "Program log: AnchorError thrown in programs/errors/src/lib.rs:97. Error Code: RequireKeysEqViolated. Error Number: 2502. Error Message: A require_keys_eq expression was violated.", "Program log: Left:", `Program log: ${someAccount}`, "Program log: Right:", @@ -416,8 +416,8 @@ describe("errors", () => { }); it("Emits a ValueMatch error via require_keys_neq", async () => { + const someAccount = program.programId; await withLogTest(async () => { - const someAccount = program.programId try { const tx = await program.rpc.requireKeysNeq({ accounts: { @@ -463,63 +463,71 @@ describe("errors", () => { ]); }); - it('Emits a ValueLessOrEqual error via require_gt', async () => { + it("Emits a ValueLessOrEqual error via require_gt", async () => { await withLogTest(async () => { try { - const tx = await program.rpc.requireGt() - assert.fail("Unexpected success in creating a transaction that should have failed with `ValueLessOrEqual` error") + const tx = await program.rpc.requireGt(); + assert.fail( + "Unexpected success in creating a transaction that should have failed with `ValueLessOrEqual` error" + ); } catch (err) { - assert.equal(err.code, 6129) + assert.equal(err.code, 6129); } }, [ "Program log: AnchorError thrown in programs/errors/src/lib.rs:116. Error Code: ValueLessOrEqual. Error Number: 6129. Error Message: ValueLessOrEqual.", "Program log: Left: 5", "Program log: Right: 10", - ]) - }) + ]); + }); - it('Emits a RequireGtViolated error via require_gt', async () => { + it("Emits a RequireGtViolated error via require_gt", async () => { await withLogTest(async () => { try { - const tx = await program.rpc.requireGtDefaultError() - assert.fail("Unexpected success in creating a transaction that should have failed with `RequireGtViolated` error") + const tx = await program.rpc.requireGtDefaultError(); + assert.fail( + "Unexpected success in creating a transaction that should have failed with `RequireGtViolated` error" + ); } catch (err) { - assert.equal(err.code, 2505) + assert.equal(err.code, 2505); } }, [ "Program log: AnchorError thrown in programs/errors/src/lib.rs:121. Error Code: RequireGtViolated. Error Number: 2505. Error Message: A require_gt expression was violated.", "Program log: Left: 10", "Program log: Right: 10", - ]) - }) + ]); + }); - it('Emits a ValueLess error via require_gte', async () => { + it("Emits a ValueLess error via require_gte", async () => { await withLogTest(async () => { try { - const tx = await program.rpc.requireGte() - assert.fail("Unexpected success in creating a transaction that should have failed with `ValueLess` error") + const tx = await program.rpc.requireGte(); + assert.fail( + "Unexpected success in creating a transaction that should have failed with `ValueLess` error" + ); } catch (err) { - assert.equal(err.code, 6128) + assert.equal(err.code, 6128); } }, [ "Program log: AnchorError thrown in programs/errors/src/lib.rs:126. Error Code: ValueLess. Error Number: 6128. Error Message: ValueLess.", "Program log: Left: 5", "Program log: Right: 10", - ]) - }) + ]); + }); - it('Emits a RequireGteViolated error via require_gte', async () => { + it("Emits a RequireGteViolated error via require_gte", async () => { await withLogTest(async () => { try { - const tx = await program.rpc.requireGteDefaultError() - assert.fail("Unexpected success in creating a transaction that should have failed with `RequireGteViolated` error") + const tx = await program.rpc.requireGteDefaultError(); + assert.fail( + "Unexpected success in creating a transaction that should have failed with `RequireGteViolated` error" + ); } catch (err) { - assert.equal(err.code, 2506) + assert.equal(err.code, 2506); } }, [ "Program log: AnchorError thrown in programs/errors/src/lib.rs:131. Error Code: RequireGteViolated. Error Number: 2506. Error Message: A require_gte expression was violated.", "Program log: Left: 5", "Program log: Right: 10", - ]) - }) + ]); + }); });