diff --git a/near-plugins-derive/src/pausable.rs b/near-plugins-derive/src/pausable.rs index 9c3dbf2..4a2f1de 100644 --- a/near-plugins-derive/src/pausable.rs +++ b/near-plugins-derive/src/pausable.rs @@ -184,13 +184,20 @@ pub fn if_paused(attrs: TokenStream, item: TokenStream) -> TokenStream { let fn_name = args.name; + // Construct error messages that use `format!` here, i.e. at compile time. Doing that during + // contract execution would cost extra gas. + let err_feature_not_paused = format!("Pausable: {fn_name} must be paused to use this function"); + let bypass_condition = get_bypass_condition(&args.except); let check_pause = quote!( let mut __check_paused = true; #bypass_condition if __check_paused { - ::near_sdk::require!(self.pa_is_paused(#fn_name.to_string()), "Pausable: Method must be paused"); + ::near_sdk::require!( + self.pa_is_paused(#fn_name.to_string()), + #err_feature_not_paused, + ); } ); diff --git a/near-plugins-derive/tests/common/utils.rs b/near-plugins-derive/tests/common/utils.rs index ef3ebd9..69d608b 100644 --- a/near-plugins-derive/tests/common/utils.rs +++ b/near-plugins-derive/tests/common/utils.rs @@ -110,6 +110,11 @@ pub fn assert_method_is_paused(res: ExecutionFinalResult) { ); } +pub fn assert_pausable_escape_hatch_is_closed(res: ExecutionFinalResult, feature: &str) { + let must_contain = format!("Pausable: {feature} must be paused to use this function"); + assert_failure_with(res, &must_contain); +} + pub fn assert_owner_update_failure(res: ExecutionFinalResult) { let err = res .into_result() diff --git a/near-plugins-derive/tests/pausable.rs b/near-plugins-derive/tests/pausable.rs index e5d0186..14fc229 100644 --- a/near-plugins-derive/tests/pausable.rs +++ b/near-plugins-derive/tests/pausable.rs @@ -6,7 +6,7 @@ use common::access_controllable_contract::AccessControllableContract; use common::pausable_contract::PausableContract; use common::utils::{ assert_failure_with, assert_insufficient_acl_permissions, assert_method_is_paused, - assert_success_with, assert_success_with_unit_return, + assert_pausable_escape_hatch_is_closed, assert_success_with, assert_success_with_unit_return, }; use near_sdk::serde_json::json; use std::collections::HashSet; @@ -17,8 +17,6 @@ use workspaces::{Account, AccountId, Contract, Worker}; const PROJECT_PATH: &str = "./tests/contracts/pausable"; -const MESSAGE_METHOD_NOT_PAUSED: &str = "Pausable: Method must be paused"; - /// Bundles resources required in tests. struct Setup { /// The worker interacting with the current sandbox. @@ -647,6 +645,6 @@ async fn test_escape_hatch_fail() -> anyhow::Result<()> { let res = setup .call_counter_modifier(&setup.unauth_account, "decrease_1") .await?; - assert_failure_with(res, MESSAGE_METHOD_NOT_PAUSED); + assert_pausable_escape_hatch_is_closed(res, "increase_1"); Ok(()) }