diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 12545de..d335673 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -25,7 +25,7 @@ jobs: override: true target: wasm32-unknown-unknown - - uses: Swatinem/rust-cache@v1 + - uses: Swatinem/rust-cache@v2 with: key: rust-version-${{ env.MSRV }}-msrv-2 @@ -33,7 +33,7 @@ jobs: run: rustup target add wasm32-unknown-unknown - name: cargo test - run: cargo test --all --all-features + run: cargo test --workspace --all-features lint: name: Format @@ -49,7 +49,7 @@ jobs: override: true components: rustfmt, clippy - - uses: Swatinem/rust-cache@v1 + - uses: Swatinem/rust-cache@v2 with: key: rust-version-${{ env.MSRV }}-msrv-2 @@ -57,4 +57,4 @@ jobs: run: cargo fmt --all -- --check - name: cargo clippy - run: cargo clippy --all --all-features --all-targets -- -D warnings + run: cargo clippy --workspace --all-features --all-targets -- -D warnings diff --git a/Cargo.toml b/Cargo.toml index e5a4c57..68c51e6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,3 +36,12 @@ proc-macro2 = "1.0" quote = "1.0.9" syn = { version = "1.0.69", features = ["full"] } proc-macro-crate = "0.1.5" + +[workspace.lints.clippy] +all = "deny" +nursery = "deny" +pedantic = "deny" + +module_name_repetitions = "allow" +missing_errors_doc = "allow" +missing_panics_doc = "allow" diff --git a/near-plugins-derive/Cargo.toml b/near-plugins-derive/Cargo.toml index 599a427..34cfb7b 100644 --- a/near-plugins-derive/Cargo.toml +++ b/near-plugins-derive/Cargo.toml @@ -22,3 +22,6 @@ near-sdk = { workspace = true, features = ["unit-testing"] } tokio.workspace = true near-workspaces.workspace = true toml.workspace = true + +[lints] +workspace = true diff --git a/near-plugins-derive/src/access_control_role.rs b/near-plugins-derive/src/access_control_role.rs index 7b98479..5b27ab4 100644 --- a/near-plugins-derive/src/access_control_role.rs +++ b/near-plugins-derive/src/access_control_role.rs @@ -73,7 +73,7 @@ pub fn derive_access_control_role(input: TokenStream) -> TokenStream { ); let variant_idxs: Vec<_> = (0..u8::try_from(variant_idents.len()).expect("Too many enum variants")).collect(); - let variant_names: Vec<_> = variant_idents.iter().map(|v| format!("{}", v)).collect(); + let variant_names: Vec<_> = variant_idents.iter().map(|v| format!("{v}")).collect(); let boundchecker_type = Ident::new(DEFAULT_BOUNDCHECKER_TYPE_NAME, ident.span()); let bitflags_type_ident = new_bitflags_type_ident(Span::call_site()); @@ -89,7 +89,7 @@ pub fn derive_access_control_role(input: TokenStream) -> TokenStream { // Without this explicit check, compilation would still fail if a bound // is not satisfied. Though with less a clear error message. struct #boundchecker_type { - _marker: ::std::marker::PhantomData, + _marker: std::marker::PhantomData, } impl #boundchecker_type { fn new() -> Self { @@ -113,7 +113,7 @@ pub fn derive_access_control_role(input: TokenStream) -> TokenStream { } } - impl ::std::convert::TryFrom for #ident { + impl std::convert::TryFrom for #ident { type Error = &'static str; fn try_from(value: u8) -> Result { @@ -146,7 +146,7 @@ pub fn derive_access_control_role(input: TokenStream) -> TokenStream { } } - impl ::std::convert::TryFrom<&str> for #ident { + impl std::convert::TryFrom<&str> for #ident { type Error = &'static str; fn try_from(value: &str) -> Result<#ident, Self::Error> { @@ -163,7 +163,7 @@ pub fn derive_access_control_role(input: TokenStream) -> TokenStream { fn safe_leftshift(value: u128, n: u8) -> u128 { value .checked_shl(n.into()) - .unwrap_or_else(|| ::near_sdk::env::panic_str("Too many enum variants to be represented by bitflags")) + .unwrap_or_else(|| near_sdk::env::panic_str("Too many enum variants to be represented by bitflags")) } impl #cratename::AccessControlRole for #ident { @@ -181,7 +181,7 @@ pub fn derive_access_control_role(input: TokenStream) -> TokenStream { fn acl_permission(self) -> u128 { // Shift 1u128 left by an odd number, see module documentation. let n = (u8::from(self) + 1) - .checked_mul(2).unwrap_or_else(|| ::near_sdk::env::panic_str("Too many enum variants")) - 1; + .checked_mul(2).unwrap_or_else(|| near_sdk::env::panic_str("Too many enum variants")) - 1; safe_leftshift(1, n) } @@ -189,7 +189,7 @@ pub fn derive_access_control_role(input: TokenStream) -> TokenStream { // Shift 1u128 left by an even number, see module documentation. let n = (u8::from(self) + 1) .checked_mul(2) - .unwrap_or_else(|| ::near_sdk::env::panic_str("Too many enum variants")); + .unwrap_or_else(|| near_sdk::env::panic_str("Too many enum variants")); safe_leftshift(1, n) } } @@ -198,8 +198,8 @@ pub fn derive_access_control_role(input: TokenStream) -> TokenStream { /// Encodes permissions for roles and admins. #[derive( Default, - ::near_sdk::borsh::BorshDeserialize, - ::near_sdk::borsh::BorshSerialize, + near_sdk::borsh::BorshDeserialize, + near_sdk::borsh::BorshSerialize, )] #[borsh(crate = "near_sdk::borsh")] struct #bitflags_type_ident: u128 { @@ -228,7 +228,7 @@ fn bitflags_idents(names: &[String], span: Span) -> Vec { .collect::>(); let admin_names = names .iter() - .map(|name| format!("{}_ADMIN", name)) + .map(|name| format!("{name}_ADMIN")) .collect::>(); let mut idents = vec![Ident::new(DEFAULT_SUPER_ADMIN_NAME, span)]; for (name, admin_name) in names.iter().zip(admin_names) { diff --git a/near-plugins-derive/src/access_controllable.rs b/near-plugins-derive/src/access_controllable.rs index 0569250..e09f818 100644 --- a/near-plugins-derive/src/access_controllable.rs +++ b/near-plugins-derive/src/access_controllable.rs @@ -49,26 +49,18 @@ pub fn access_controllable(attrs: TokenStream, item: TokenStream) -> TokenStream let output = quote! { #input - #[derive(::near_sdk::borsh::BorshDeserialize, ::near_sdk::borsh::BorshSerialize)] + #[derive(near_sdk::borsh::BorshDeserialize, near_sdk::borsh::BorshSerialize)] #[borsh(crate = "near_sdk::borsh")] - /// NOTE: Despite `near_sdk::store::UnorderedMap` and `near_sdk::store::UnorderedSet` - /// have been deprecated, it still makes sense to use them here as we might still - /// need to iterate over the keys. - /// The impact on gas consumption compared to `near_sdk::store::LookupMap` is negligible - /// as it lazily loads list of keys to iterate over internally. Compiled size of a - /// contract is not affected that much as well. struct #acl_type { /// Stores permissions per account. - #[allow(deprecated)] - permissions: ::near_sdk::store::UnorderedMap< - ::near_sdk::AccountId, + permissions: near_sdk::store::IterableMap< + near_sdk::AccountId, #bitflags_type, >, /// Stores the set of accounts that bear a permission. - #[allow(deprecated)] - bearers: ::near_sdk::store::UnorderedMap< + bearers: near_sdk::store::IterableMap< #bitflags_type, - ::near_sdk::store::UnorderedSet<::near_sdk::AccountId>, + near_sdk::store::IterableSet, >, } @@ -76,12 +68,10 @@ pub fn access_controllable(attrs: TokenStream, item: TokenStream) -> TokenStream fn default() -> Self { let base_prefix = <#ident as #cratename::AccessControllable>::acl_storage_prefix(); Self { - #[allow(deprecated)] - permissions: ::near_sdk::store::UnorderedMap::new( + permissions: near_sdk::store::IterableMap::new( __acl_storage_prefix(base_prefix, __AclStorageKey::Permissions), ), - #[allow(deprecated)] - bearers: ::near_sdk::store::UnorderedMap::new( + bearers: near_sdk::store::IterableMap::new( __acl_storage_prefix(base_prefix, __AclStorageKey::Bearers), ), } @@ -91,7 +81,7 @@ pub fn access_controllable(attrs: TokenStream, item: TokenStream) -> TokenStream /// Used to make storage prefixes unique. Not to be used directly, /// instead it should be prepended to the storage prefix specified by /// the user. - #[derive(::near_sdk::borsh::BorshSerialize)] + #[derive(near_sdk::borsh::BorshSerialize)] #[borsh(crate = "near_sdk::borsh")] enum __AclStorageKey { Permissions, @@ -103,7 +93,7 @@ pub fn access_controllable(attrs: TokenStream, item: TokenStream) -> TokenStream /// Generates a prefix by concatenating the input parameters. fn __acl_storage_prefix(base: &[u8], specifier: __AclStorageKey) -> Vec { let specifier = near_sdk::borsh::to_vec(&specifier) - .unwrap_or_else(|_| ::near_sdk::env::panic_str("Storage key should be serializable")); + .unwrap_or_else(|_| near_sdk::env::panic_str("Storage key should be serializable")); [base, specifier.as_slice()].concat() } @@ -115,7 +105,7 @@ pub fn access_controllable(attrs: TokenStream, item: TokenStream) -> TokenStream __AclStorageKey::AclStorage, )) .map(|acl_storage_bytes| { - ::near_sdk::borsh::BorshDeserialize::try_from_slice(&acl_storage_bytes) + near_sdk::borsh::BorshDeserialize::try_from_slice(&acl_storage_bytes) .unwrap_or_else(|_| near_sdk::env::panic_str("ACL: invalid acl storage format")) }) } @@ -136,32 +126,31 @@ pub fn access_controllable(attrs: TokenStream, item: TokenStream) -> TokenStream } impl #acl_type { - #[allow(deprecated)] - fn new_bearers_set(permission: #bitflags_type) -> ::near_sdk::store::UnorderedSet<::near_sdk::AccountId> { + fn new_bearers_set(permission: #bitflags_type) -> near_sdk::store::IterableSet { let base_prefix = <#ident as #cratename::AccessControllable>::acl_storage_prefix(); let specifier = __AclStorageKey::BearersSet { permission }; - ::near_sdk::store::UnorderedSet::new(__acl_storage_prefix(base_prefix, specifier)) + near_sdk::store::IterableSet::new(__acl_storage_prefix(base_prefix, specifier)) } - fn get_or_insert_permissions(&mut self, account_id: ::near_sdk::AccountId) -> &mut #bitflags_type { + fn get_or_insert_permissions(&mut self, account_id: near_sdk::AccountId) -> &mut #bitflags_type { self.permissions.entry(account_id).or_insert_with(|| #bitflags_type::empty()) } - fn init_super_admin(&mut self, account_id: &::near_sdk::AccountId) -> bool { + fn init_super_admin(&mut self, account_id: &near_sdk::AccountId) -> bool { let permission = <#bitflags_type>::from_bits(<#role_type>::acl_super_admin_permission()) - .unwrap_or_else(|| ::near_sdk::env::panic_str(#ERR_PARSE_BITFLAG)); + .unwrap_or_else(|| near_sdk::env::panic_str(#ERR_PARSE_BITFLAG)); // Taking 1 at offset 0 is enough to check if there are no super admins assigned. let super_admins = self.get_bearers(permission, 0, 1); if super_admins.len() > 0 { return false; } let res = self.add_super_admin_unchecked(account_id); - ::near_sdk::require!(res, "Failed to init super-admin."); + near_sdk::require!(res, "Failed to init super-admin."); res } - fn add_super_admin(&mut self, account_id: &::near_sdk::AccountId) -> Option { - if !self.is_super_admin(&::near_sdk::env::predecessor_account_id()) { + fn add_super_admin(&mut self, account_id: &near_sdk::AccountId) -> Option { + if !self.is_super_admin(&near_sdk::env::predecessor_account_id()) { return None; } Some(self.add_super_admin_unchecked(account_id)) @@ -171,9 +160,9 @@ pub fn access_controllable(attrs: TokenStream, item: TokenStream) -> TokenStream /// It returns whether `account_id` is a new super-admin. /// /// Note that there may be zero or more super-admins. - fn add_super_admin_unchecked(&mut self, account_id: &::near_sdk::AccountId) -> bool { + fn add_super_admin_unchecked(&mut self, account_id: &near_sdk::AccountId) -> bool { let flag = <#bitflags_type>::from_bits(<#role_type>::acl_super_admin_permission()) - .unwrap_or_else(|| ::near_sdk::env::panic_str(#ERR_PARSE_BITFLAG)); + .unwrap_or_else(|| near_sdk::env::panic_str(#ERR_PARSE_BITFLAG)); let mut permissions = self.get_or_insert_permissions(account_id.clone()); let is_new_super_admin = !permissions.contains(flag); @@ -183,7 +172,7 @@ pub fn access_controllable(attrs: TokenStream, item: TokenStream) -> TokenStream let event = #cratename::access_controllable::events::SuperAdminAdded { account: account_id.clone(), - by: ::near_sdk::env::predecessor_account_id(), + by: near_sdk::env::predecessor_account_id(), }; #cratename::events::AsEvent::emit(&event); } @@ -191,7 +180,7 @@ pub fn access_controllable(attrs: TokenStream, item: TokenStream) -> TokenStream is_new_super_admin } - fn is_super_admin(&self, account_id: &::near_sdk::AccountId) -> bool { + fn is_super_admin(&self, account_id: &near_sdk::AccountId) -> bool { let permissions = { match self.permissions.get(account_id) { Some(permissions) => permissions, @@ -199,19 +188,19 @@ pub fn access_controllable(attrs: TokenStream, item: TokenStream) -> TokenStream } }; let super_admin = <#bitflags_type>::from_bits(<#role_type>::acl_super_admin_permission()) - .unwrap_or_else(|| ::near_sdk::env::panic_str(#ERR_PARSE_BITFLAG)); + .unwrap_or_else(|| near_sdk::env::panic_str(#ERR_PARSE_BITFLAG)); permissions.contains(super_admin) } - fn revoke_super_admin(&mut self, account_id: &::near_sdk::AccountId) -> Option { - if !self.is_super_admin(&::near_sdk::env::predecessor_account_id()) { + fn revoke_super_admin(&mut self, account_id: &near_sdk::AccountId) -> Option { + if !self.is_super_admin(&near_sdk::env::predecessor_account_id()) { return None; } Some(self.revoke_super_admin_unchecked(account_id)) } - fn transfer_super_admin(&mut self, account_id: &::near_sdk::AccountId) -> Option { - let current_super_admin = ::near_sdk::env::predecessor_account_id(); + fn transfer_super_admin(&mut self, account_id: &near_sdk::AccountId) -> Option { + let current_super_admin = near_sdk::env::predecessor_account_id(); if !self.is_super_admin(¤t_super_admin) { return None; } @@ -238,9 +227,9 @@ pub fn access_controllable(attrs: TokenStream, item: TokenStream) -> TokenStream /// Revokes super-admin permissions from `account_id` without checking any /// permissions. It returns whether `account_id` was a super-admin. - fn revoke_super_admin_unchecked(&mut self, account_id: &::near_sdk::AccountId) -> bool { + fn revoke_super_admin_unchecked(&mut self, account_id: &near_sdk::AccountId) -> bool { let flag = <#bitflags_type>::from_bits(<#role_type>::acl_super_admin_permission()) - .unwrap_or_else(|| ::near_sdk::env::panic_str(#ERR_PARSE_BITFLAG)); + .unwrap_or_else(|| near_sdk::env::panic_str(#ERR_PARSE_BITFLAG)); let mut permissions = match self.permissions.get_mut(account_id) { Some(permissions) => permissions, None => return false, // nothing to do, account has no permissions @@ -253,7 +242,7 @@ pub fn access_controllable(attrs: TokenStream, item: TokenStream) -> TokenStream let event = #cratename::access_controllable::events::SuperAdminRevoked { account: account_id.clone(), - by: ::near_sdk::env::predecessor_account_id(), + by: near_sdk::env::predecessor_account_id(), }; #cratename::events::AsEvent::emit(&event); } @@ -261,8 +250,8 @@ pub fn access_controllable(attrs: TokenStream, item: TokenStream) -> TokenStream was_super_admin } - fn add_admin(&mut self, role: #role_type, account_id: &::near_sdk::AccountId) -> Option { - if !self.is_admin(role, &::near_sdk::env::predecessor_account_id()) { + fn add_admin(&mut self, role: #role_type, account_id: &near_sdk::AccountId) -> Option { + if !self.is_admin(role, &near_sdk::env::predecessor_account_id()) { return None; } Some(self.add_admin_unchecked(role, account_id)) @@ -272,9 +261,9 @@ pub fn access_controllable(attrs: TokenStream, item: TokenStream) -> TokenStream /// permissions. Returns whether `account_id` is a new admin for `role`. /// /// Note that any role may have multiple (or zero) admins. - fn add_admin_unchecked(&mut self, role: #role_type, account_id: &::near_sdk::AccountId) -> bool { + fn add_admin_unchecked(&mut self, role: #role_type, account_id: &near_sdk::AccountId) -> bool { let flag = <#bitflags_type>::from_bits(role.acl_admin_permission()) - .unwrap_or_else(|| ::near_sdk::env::panic_str(#ERR_PARSE_BITFLAG)); + .unwrap_or_else(|| near_sdk::env::panic_str(#ERR_PARSE_BITFLAG)); let mut permissions = self.get_or_insert_permissions(account_id.clone()); let is_new_admin = !permissions.contains(flag); @@ -285,7 +274,7 @@ pub fn access_controllable(attrs: TokenStream, item: TokenStream) -> TokenStream let event = #cratename::access_controllable::events::AdminAdded { role: role.into(), account: account_id.clone(), - by: ::near_sdk::env::predecessor_account_id(), + by: near_sdk::env::predecessor_account_id(), }; #cratename::events::AsEvent::emit(&event); } @@ -293,7 +282,7 @@ pub fn access_controllable(attrs: TokenStream, item: TokenStream) -> TokenStream is_new_admin } - fn is_admin(&self, role: #role_type, account_id: &::near_sdk::AccountId) -> bool { + fn is_admin(&self, role: #role_type, account_id: &near_sdk::AccountId) -> bool { let permissions = { match self.permissions.get(account_id) { Some(permissions) => permissions, @@ -301,28 +290,28 @@ pub fn access_controllable(attrs: TokenStream, item: TokenStream) -> TokenStream } }; let super_admin = <#bitflags_type>::from_bits(<#role_type>::acl_super_admin_permission()) - .unwrap_or_else(|| ::near_sdk::env::panic_str(#ERR_PARSE_BITFLAG)); + .unwrap_or_else(|| near_sdk::env::panic_str(#ERR_PARSE_BITFLAG)); let role_admin = <#bitflags_type>::from_bits(role.acl_admin_permission()) - .unwrap_or_else(|| ::near_sdk::env::panic_str(#ERR_PARSE_BITFLAG)); + .unwrap_or_else(|| near_sdk::env::panic_str(#ERR_PARSE_BITFLAG)); permissions.contains(super_admin) || permissions.contains(role_admin) } - fn revoke_admin(&mut self, role: #role_type, account_id: &::near_sdk::AccountId) -> Option { - if !self.is_admin(role, &::near_sdk::env::predecessor_account_id()) { + fn revoke_admin(&mut self, role: #role_type, account_id: &near_sdk::AccountId) -> Option { + if !self.is_admin(role, &near_sdk::env::predecessor_account_id()) { return None; } Some(self.revoke_admin_unchecked(role, account_id)) } fn renounce_admin(&mut self, role: #role_type) -> bool { - self.revoke_admin_unchecked(role, &::near_sdk::env::predecessor_account_id()) + self.revoke_admin_unchecked(role, &near_sdk::env::predecessor_account_id()) } /// Revokes admin permissions from `account_id` __without__ checking any /// permissions. Returns whether `account_id` was an admin for `role`. - fn revoke_admin_unchecked(&mut self, role: #role_type, account_id: &::near_sdk::AccountId) -> bool { + fn revoke_admin_unchecked(&mut self, role: #role_type, account_id: &near_sdk::AccountId) -> bool { let flag = <#bitflags_type>::from_bits(role.acl_admin_permission()) - .unwrap_or_else(|| ::near_sdk::env::panic_str(#ERR_PARSE_BITFLAG)); + .unwrap_or_else(|| near_sdk::env::panic_str(#ERR_PARSE_BITFLAG)); let mut permissions = match self.permissions.get_mut(account_id) { Some(permissions) => permissions, None => return false, // nothing to do, account has no permissions @@ -336,7 +325,7 @@ pub fn access_controllable(attrs: TokenStream, item: TokenStream) -> TokenStream let event = #cratename::access_controllable::events::AdminRevoked { role: role.into(), account: account_id.clone(), - by: ::near_sdk::env::predecessor_account_id(), + by: near_sdk::env::predecessor_account_id(), }; #cratename::events::AsEvent::emit(&event); } @@ -344,8 +333,8 @@ pub fn access_controllable(attrs: TokenStream, item: TokenStream) -> TokenStream was_admin } - fn grant_role(&mut self, role: #role_type, account_id: &::near_sdk::AccountId) -> Option { - if !self.is_admin(role, &::near_sdk::env::predecessor_account_id()) { + fn grant_role(&mut self, role: #role_type, account_id: &near_sdk::AccountId) -> Option { + if !self.is_admin(role, &near_sdk::env::predecessor_account_id()) { return None; } Some(self.grant_role_unchecked(role, account_id)) @@ -353,9 +342,9 @@ pub fn access_controllable(attrs: TokenStream, item: TokenStream) -> TokenStream /// Grants `role` to `account_id` __without__ checking any permissions. /// Returns whether `role` was newly granted to `account_id`. - fn grant_role_unchecked(&mut self, role: #role_type, account_id: &::near_sdk::AccountId) -> bool { + fn grant_role_unchecked(&mut self, role: #role_type, account_id: &near_sdk::AccountId) -> bool { let flag = <#bitflags_type>::from_bits(role.acl_permission()) - .unwrap_or_else(|| ::near_sdk::env::panic_str(#ERR_PARSE_BITFLAG)); + .unwrap_or_else(|| near_sdk::env::panic_str(#ERR_PARSE_BITFLAG)); let mut permissions = self.get_or_insert_permissions(account_id.clone()); let is_new_grantee = !permissions.contains(flag); @@ -365,7 +354,7 @@ pub fn access_controllable(attrs: TokenStream, item: TokenStream) -> TokenStream let event = #cratename::access_controllable::events::RoleGranted { role: role.into(), - by: ::near_sdk::env::predecessor_account_id(), + by: near_sdk::env::predecessor_account_id(), to: account_id.clone(), }; #cratename::events::AsEvent::emit(&event); @@ -374,20 +363,20 @@ pub fn access_controllable(attrs: TokenStream, item: TokenStream) -> TokenStream is_new_grantee } - fn revoke_role(&mut self, role: #role_type, account_id: &::near_sdk::AccountId) -> Option { - if !self.is_admin(role, &::near_sdk::env::predecessor_account_id()) { + fn revoke_role(&mut self, role: #role_type, account_id: &near_sdk::AccountId) -> Option { + if !self.is_admin(role, &near_sdk::env::predecessor_account_id()) { return None; } Some(self.revoke_role_unchecked(role, account_id)) } fn renounce_role(&mut self, role: #role_type) -> bool { - self.revoke_role_unchecked(role, &::near_sdk::env::predecessor_account_id()) + self.revoke_role_unchecked(role, &near_sdk::env::predecessor_account_id()) } - fn revoke_role_unchecked(&mut self, role: #role_type, account_id: &::near_sdk::AccountId) -> bool { + fn revoke_role_unchecked(&mut self, role: #role_type, account_id: &near_sdk::AccountId) -> bool { let flag = <#bitflags_type>::from_bits(role.acl_permission()) - .unwrap_or_else(|| ::near_sdk::env::panic_str(#ERR_PARSE_BITFLAG)); + .unwrap_or_else(|| near_sdk::env::panic_str(#ERR_PARSE_BITFLAG)); let mut permissions = match self.permissions.get_mut(account_id) { Some(permissions) => permissions, None => return false, // nothing to do, account has no permissions @@ -401,7 +390,7 @@ pub fn access_controllable(attrs: TokenStream, item: TokenStream) -> TokenStream let event = #cratename::access_controllable::events::RoleRevoked { role: role.into(), from: account_id.clone(), - by: ::near_sdk::env::predecessor_account_id(), + by: near_sdk::env::predecessor_account_id(), }; #cratename::events::AsEvent::emit(&event); } @@ -409,11 +398,11 @@ pub fn access_controllable(attrs: TokenStream, item: TokenStream) -> TokenStream was_grantee } - fn has_role(&self, role: #role_type, account_id: &::near_sdk::AccountId) -> bool { + fn has_role(&self, role: #role_type, account_id: &near_sdk::AccountId) -> bool { match self.permissions.get(account_id) { Some(permissions) => { let flag = <#bitflags_type>::from_bits(role.acl_permission()) - .unwrap_or_else(|| ::near_sdk::env::panic_str(#ERR_PARSE_BITFLAG)); + .unwrap_or_else(|| near_sdk::env::panic_str(#ERR_PARSE_BITFLAG)); permissions.contains(flag) } None => false, @@ -422,14 +411,14 @@ pub fn access_controllable(attrs: TokenStream, item: TokenStream) -> TokenStream fn has_any_role( &self, roles: Vec<#role_type>, - account_id: &::near_sdk::AccountId + account_id: &near_sdk::AccountId ) -> bool { // Create a bitflags value with active bits for all `roles`. let target = roles .iter() .map(|role| { <#bitflags_type>::from_bits(role.acl_permission()) - .unwrap_or_else(|| ::near_sdk::env::panic_str(#ERR_PARSE_BITFLAG)) + .unwrap_or_else(|| near_sdk::env::panic_str(#ERR_PARSE_BITFLAG)) }) .fold( <#bitflags_type>::empty(), @@ -438,7 +427,7 @@ pub fn access_controllable(attrs: TokenStream, item: TokenStream) -> TokenStream self.has_any_permission(target, account_id) } - fn has_any_permission(&self, target: #bitflags_type, account_id: &::near_sdk::AccountId) -> bool { + fn has_any_permission(&self, target: #bitflags_type, account_id: &near_sdk::AccountId) -> bool { let permissions = match self.permissions.get(account_id) { Some(&permissions) => permissions, None => return false, @@ -455,8 +444,8 @@ pub fn access_controllable(attrs: TokenStream, item: TokenStream) -> TokenStream /// developers might call this function with a `permission` that has /// multiple active bits. In that case, the panic prevents polluting /// state. - fn add_bearer(&mut self, permission: #bitflags_type, account_id: &::near_sdk::AccountId) { - ::near_sdk::require!( + fn add_bearer(&mut self, permission: #bitflags_type, account_id: &near_sdk::AccountId) { + near_sdk::require!( permission.bits().is_power_of_two(), "Adding a bearer is allowed only for permissions with exactly one active bit" ); @@ -472,9 +461,9 @@ pub fn access_controllable(attrs: TokenStream, item: TokenStream) -> TokenStream /// # Panics /// /// Panics if `skip` or `limit` are outside the range of `usize`. - fn get_bearers(&self, permission: #bitflags_type, skip: u64, limit: u64) -> Vec<::near_sdk::AccountId> { - let skip: usize = ::std::convert::TryFrom::try_from(skip).unwrap_or_else(|_| ::near_sdk::env::panic_str("skip should be in the range of usize")); - let limit: usize = ::std::convert::TryFrom::try_from(limit).unwrap_or_else(|_| ::near_sdk::env::panic_str("limit should be in the range of usize")); + fn get_bearers(&self, permission: #bitflags_type, skip: u64, limit: u64) -> Vec { + let skip: usize = std::convert::TryFrom::try_from(skip).unwrap_or_else(|_| near_sdk::env::panic_str("skip should be in the range of usize")); + let limit: usize = std::convert::TryFrom::try_from(limit).unwrap_or_else(|_| near_sdk::env::panic_str("limit should be in the range of usize")); let set = match self.bearers.get(&permission) { Some(set) => set, None => return vec![], @@ -485,7 +474,7 @@ pub fn access_controllable(attrs: TokenStream, item: TokenStream) -> TokenStream /// Returns _all_ bearers of `permission`. In this implementation of /// `AccessControllable` there is no upper bound on the number of bearers per /// permission, so gas limits should be considered when calling this function. - fn get_all_bearers(&self, permission: #bitflags_type) -> Vec<::near_sdk::AccountId> { + fn get_all_bearers(&self, permission: #bitflags_type) -> Vec { let set = match self.bearers.get(&permission) { Some(set) => set, None => return vec![], @@ -494,7 +483,7 @@ pub fn access_controllable(attrs: TokenStream, item: TokenStream) -> TokenStream } /// Removes `account_id` from the set of `permission` bearers. - fn remove_bearer(&mut self, permission: #bitflags_type, account_id: &::near_sdk::AccountId) { + fn remove_bearer(&mut self, permission: #bitflags_type, account_id: &near_sdk::AccountId) { // If `permission` is invalid (more than one active bit), this // function is a no-op, due to the check in `add_bearer`. let mut set = match self.bearers.get_mut(&permission) { @@ -513,21 +502,21 @@ pub fn access_controllable(attrs: TokenStream, item: TokenStream) -> TokenStream let permission = <#bitflags_type>::from_bits( <#role_type>::acl_super_admin_permission() ) - .unwrap_or_else(|| ::near_sdk::env::panic_str(#ERR_PARSE_BITFLAG)); + .unwrap_or_else(|| near_sdk::env::panic_str(#ERR_PARSE_BITFLAG)); let super_admins = self.get_all_bearers(permission); // Get admins and grantees per role. let roles = <#role_type>::acl_role_variants(); - let mut map = ::std::collections::HashMap::new(); + let mut map = std::collections::HashMap::new(); for role in roles { - let role: #role_type = ::std::convert::TryFrom::try_from(role) - .unwrap_or_else(|_| ::near_sdk::env::panic_str(#ERR_PARSE_ROLE)); + let role: #role_type = std::convert::TryFrom::try_from(role) + .unwrap_or_else(|_| near_sdk::env::panic_str(#ERR_PARSE_ROLE)); let admin_permission = <#bitflags_type>::from_bits(role.acl_admin_permission()) - .unwrap_or_else(|| ::near_sdk::env::panic_str(#ERR_PARSE_BITFLAG)); + .unwrap_or_else(|| near_sdk::env::panic_str(#ERR_PARSE_BITFLAG)); let admins = self.get_all_bearers(admin_permission); let grantee_permission = <#bitflags_type>::from_bits(role.acl_permission()) - .unwrap_or_else(|| ::near_sdk::env::panic_str(#ERR_PARSE_BITFLAG)); + .unwrap_or_else(|| near_sdk::env::panic_str(#ERR_PARSE_BITFLAG)); let grantees = self.get_all_bearers(grantee_permission); map.insert( @@ -548,10 +537,10 @@ pub fn access_controllable(attrs: TokenStream, item: TokenStream) -> TokenStream fn get_default_permissioned_accounts() -> #cratename::access_controllable::PermissionedAccounts { let roles = <#role_type>::acl_role_variants(); - let mut map = ::std::collections::HashMap::new(); + let mut map = std::collections::HashMap::new(); for role in roles { - let role: #role_type = ::std::convert::TryFrom::try_from(role) - .unwrap_or_else(|_| ::near_sdk::env::panic_str(#ERR_PARSE_ROLE)); + let role: #role_type = std::convert::TryFrom::try_from(role) + .unwrap_or_else(|_| near_sdk::env::panic_str(#ERR_PARSE_ROLE)); map.insert( role.into(), @@ -591,11 +580,11 @@ pub fn access_controllable(attrs: TokenStream, item: TokenStream) -> TokenStream } #[private] - fn acl_init_super_admin(&mut self, account_id: ::near_sdk::AccountId) -> bool { + fn acl_init_super_admin(&mut self, account_id: near_sdk::AccountId) -> bool { self.acl_get_or_init().init_super_admin(&account_id) } - fn acl_add_super_admin(&mut self, account_id: ::near_sdk::AccountId) -> Option { + fn acl_add_super_admin(&mut self, account_id: near_sdk::AccountId) -> Option { self.acl_get_or_init().add_super_admin(&account_id) } @@ -603,88 +592,88 @@ pub fn access_controllable(attrs: TokenStream, item: TokenStream) -> TokenStream <#role_type>::acl_role_variants() } - fn acl_is_super_admin(&self, account_id: ::near_sdk::AccountId) -> bool { + fn acl_is_super_admin(&self, account_id: near_sdk::AccountId) -> bool { return_if_none!(self.acl_get_storage(), false).is_super_admin(&account_id) } - fn acl_revoke_super_admin(&mut self, account_id: ::near_sdk::AccountId) -> Option { + fn acl_revoke_super_admin(&mut self, account_id: near_sdk::AccountId) -> Option { self.acl_get_or_init().revoke_super_admin(&account_id) } - fn acl_transfer_super_admin(&mut self, account_id: ::near_sdk::AccountId) -> Option { + fn acl_transfer_super_admin(&mut self, account_id: near_sdk::AccountId) -> Option { self.acl_get_or_init().transfer_super_admin(&account_id) } - fn acl_add_admin(&mut self, role: String, account_id: ::near_sdk::AccountId) -> Option { - let role: #role_type = ::std::convert::TryFrom::try_from(role.as_str()).unwrap_or_else(|_| ::near_sdk::env::panic_str(#ERR_PARSE_ROLE)); + fn acl_add_admin(&mut self, role: String, account_id: near_sdk::AccountId) -> Option { + let role: #role_type = std::convert::TryFrom::try_from(role.as_str()).unwrap_or_else(|_| near_sdk::env::panic_str(#ERR_PARSE_ROLE)); self.acl_get_or_init().add_admin(role, &account_id) } - fn acl_is_admin(&self, role: String, account_id: ::near_sdk::AccountId) -> bool { - let role: #role_type = ::std::convert::TryFrom::try_from(role.as_str()).unwrap_or_else(|_| ::near_sdk::env::panic_str(#ERR_PARSE_ROLE)); + fn acl_is_admin(&self, role: String, account_id: near_sdk::AccountId) -> bool { + let role: #role_type = std::convert::TryFrom::try_from(role.as_str()).unwrap_or_else(|_| near_sdk::env::panic_str(#ERR_PARSE_ROLE)); return_if_none!(self.acl_get_storage(), false).is_admin(role, &account_id) } - fn acl_revoke_admin(&mut self, role: String, account_id: ::near_sdk::AccountId) -> Option { - let role: #role_type = ::std::convert::TryFrom::try_from(role.as_str()).unwrap_or_else(|_| ::near_sdk::env::panic_str(#ERR_PARSE_ROLE)); + fn acl_revoke_admin(&mut self, role: String, account_id: near_sdk::AccountId) -> Option { + let role: #role_type = std::convert::TryFrom::try_from(role.as_str()).unwrap_or_else(|_| near_sdk::env::panic_str(#ERR_PARSE_ROLE)); self.acl_get_or_init().revoke_admin(role, &account_id) } fn acl_renounce_admin(&mut self, role: String) -> bool { - let role: #role_type = ::std::convert::TryFrom::try_from(role.as_str()).unwrap_or_else(|_| ::near_sdk::env::panic_str(#ERR_PARSE_ROLE)); + let role: #role_type = std::convert::TryFrom::try_from(role.as_str()).unwrap_or_else(|_| near_sdk::env::panic_str(#ERR_PARSE_ROLE)); self.acl_get_or_init().renounce_admin(role) } - fn acl_revoke_role(&mut self, role: String, account_id: ::near_sdk::AccountId) -> Option { - let role: #role_type = ::std::convert::TryFrom::try_from(role.as_str()).unwrap_or_else(|_| ::near_sdk::env::panic_str(#ERR_PARSE_ROLE)); + fn acl_revoke_role(&mut self, role: String, account_id: near_sdk::AccountId) -> Option { + let role: #role_type = std::convert::TryFrom::try_from(role.as_str()).unwrap_or_else(|_| near_sdk::env::panic_str(#ERR_PARSE_ROLE)); self.acl_get_or_init().revoke_role(role, &account_id) } fn acl_renounce_role(&mut self, role: String) -> bool { - let role: #role_type = ::std::convert::TryFrom::try_from(role.as_str()).unwrap_or_else(|_| ::near_sdk::env::panic_str(#ERR_PARSE_ROLE)); + let role: #role_type = std::convert::TryFrom::try_from(role.as_str()).unwrap_or_else(|_| near_sdk::env::panic_str(#ERR_PARSE_ROLE)); self.acl_get_or_init().renounce_role(role) } - fn acl_grant_role(&mut self, role: String, account_id: ::near_sdk::AccountId) -> Option { - let role: #role_type = ::std::convert::TryFrom::try_from(role.as_str()).unwrap_or_else(|_| ::near_sdk::env::panic_str(#ERR_PARSE_ROLE)); + fn acl_grant_role(&mut self, role: String, account_id: near_sdk::AccountId) -> Option { + let role: #role_type = std::convert::TryFrom::try_from(role.as_str()).unwrap_or_else(|_| near_sdk::env::panic_str(#ERR_PARSE_ROLE)); self.acl_get_or_init().grant_role(role, &account_id) } - fn acl_has_role(&self, role: String, account_id: ::near_sdk::AccountId) -> bool { - let role: #role_type = ::std::convert::TryFrom::try_from(role.as_str()).unwrap_or_else(|_| ::near_sdk::env::panic_str(#ERR_PARSE_ROLE)); + fn acl_has_role(&self, role: String, account_id: near_sdk::AccountId) -> bool { + let role: #role_type = std::convert::TryFrom::try_from(role.as_str()).unwrap_or_else(|_| near_sdk::env::panic_str(#ERR_PARSE_ROLE)); return_if_none!(self.acl_get_storage(), false).has_role(role, &account_id) } - fn acl_has_any_role(&self, roles: Vec, account_id: ::near_sdk::AccountId) -> bool { + fn acl_has_any_role(&self, roles: Vec, account_id: near_sdk::AccountId) -> bool { let roles: Vec<#role_type> = roles .iter() .map(|role| { - ::std::convert::TryFrom::try_from(role.as_str()).unwrap_or_else(|_| ::near_sdk::env::panic_str(#ERR_PARSE_ROLE)) + std::convert::TryFrom::try_from(role.as_str()).unwrap_or_else(|_| near_sdk::env::panic_str(#ERR_PARSE_ROLE)) }) .collect(); return_if_none!(self.acl_get_storage(), false).has_any_role(roles, &account_id) } - fn acl_get_super_admins(&self, skip: u64, limit: u64) -> Vec<::near_sdk::AccountId> { + fn acl_get_super_admins(&self, skip: u64, limit: u64) -> Vec { let permission = <#bitflags_type>::from_bits( <#role_type>::acl_super_admin_permission() ) - .unwrap_or_else(|| ::near_sdk::env::panic_str(#ERR_PARSE_BITFLAG)); + .unwrap_or_else(|| near_sdk::env::panic_str(#ERR_PARSE_BITFLAG)); return_if_none!(self.acl_get_storage(), vec![]).get_bearers(permission, skip, limit) } - fn acl_get_admins(&self, role: String, skip: u64, limit: u64) -> Vec<::near_sdk::AccountId> { - let role: #role_type = ::std::convert::TryFrom::try_from(role.as_str()).unwrap_or_else(|_| ::near_sdk::env::panic_str(#ERR_PARSE_ROLE)); + fn acl_get_admins(&self, role: String, skip: u64, limit: u64) -> Vec { + let role: #role_type = std::convert::TryFrom::try_from(role.as_str()).unwrap_or_else(|_| near_sdk::env::panic_str(#ERR_PARSE_ROLE)); let permission = <#bitflags_type>::from_bits(role.acl_admin_permission()) - .unwrap_or_else(|| ::near_sdk::env::panic_str(#ERR_PARSE_BITFLAG)); + .unwrap_or_else(|| near_sdk::env::panic_str(#ERR_PARSE_BITFLAG)); return_if_none!(self.acl_get_storage(), vec![]).get_bearers(permission, skip, limit) } - fn acl_get_grantees(&self, role: String, skip: u64, limit: u64) -> Vec<::near_sdk::AccountId> { - let role: #role_type = ::std::convert::TryFrom::try_from(role.as_str()).unwrap_or_else(|_| ::near_sdk::env::panic_str(#ERR_PARSE_ROLE)); + fn acl_get_grantees(&self, role: String, skip: u64, limit: u64) -> Vec { + let role: #role_type = std::convert::TryFrom::try_from(role.as_str()).unwrap_or_else(|_| near_sdk::env::panic_str(#ERR_PARSE_ROLE)); let permission = <#bitflags_type>::from_bits(role.acl_permission()) - .unwrap_or_else(|| ::near_sdk::env::panic_str(#ERR_PARSE_BITFLAG)); + .unwrap_or_else(|| near_sdk::env::panic_str(#ERR_PARSE_BITFLAG)); return_if_none!(self.acl_get_storage(), vec![]).get_bearers(permission, skip, limit) } @@ -728,7 +717,7 @@ pub fn access_control_any(attrs: TokenStream, item: TokenStream) -> TokenStream let __acl_any_roles: Vec<&str> = vec![#(#roles.into()),*]; let __acl_any_roles_ser: Vec = __acl_any_roles.iter().map(|&role| role.into()).collect(); - let __acl_any_account_id = ::near_sdk::env::predecessor_account_id(); + let __acl_any_account_id = near_sdk::env::predecessor_account_id(); if !self.acl_has_any_role(__acl_any_roles_ser, __acl_any_account_id) { let message = format!( "Insufficient permissions for method {} restricted by access control. Requires one of these roles: {:?}", @@ -739,5 +728,5 @@ pub fn access_control_any(attrs: TokenStream, item: TokenStream) -> TokenStream } }; - utils::add_extra_code_to_fn(&input, acl_check) + utils::add_extra_code_to_fn(&input, &acl_check) } diff --git a/near-plugins-derive/src/lib.rs b/near-plugins-derive/src/lib.rs index 3a360dc..e4745c2 100644 --- a/near-plugins-derive/src/lib.rs +++ b/near-plugins-derive/src/lib.rs @@ -1,3 +1,8 @@ +#![allow( + clippy::cognitive_complexity, + clippy::collection_is_never_read, + clippy::too_many_lines +)] use proc_macro::{self, TokenStream}; mod access_control_role; diff --git a/near-plugins-derive/src/ownable.rs b/near-plugins-derive/src/ownable.rs index 0404646..794001d 100644 --- a/near-plugins-derive/src/ownable.rs +++ b/near-plugins-derive/src/ownable.rs @@ -30,20 +30,20 @@ pub fn derive_ownable(input: TokenStream) -> TokenStream { (#owner_storage_key).as_bytes() } - fn owner_get(&self) -> Option<::near_sdk::AccountId> { - ::near_sdk::env::storage_read(&self.owner_storage_key()).map(|owner_bytes| { + fn owner_get(&self) -> Option { + near_sdk::env::storage_read(&self.owner_storage_key()).map(|owner_bytes| { let owner_raw = - String::from_utf8(owner_bytes).unwrap_or_else(|_| ::near_sdk::env::panic_str("Ownable: Invalid string format")); - std::convert::TryInto::try_into(owner_raw).unwrap_or_else(|_| ::near_sdk::env::panic_str("Ownable: Invalid account id")) + String::from_utf8(owner_bytes).unwrap_or_else(|_| near_sdk::env::panic_str("Ownable: Invalid string format")); + std::convert::TryInto::try_into(owner_raw).unwrap_or_else(|_| near_sdk::env::panic_str("Ownable: Invalid account id")) }) } - fn owner_set(&mut self, owner: Option<::near_sdk::AccountId>) { + fn owner_set(&mut self, owner: Option) { let current_owner = self.owner_get(); if let Some(owner) = current_owner.as_ref() { assert_eq!( - &::near_sdk::env::predecessor_account_id(), + &near_sdk::env::predecessor_account_id(), owner, "Ownable: Only owner can update current owner" ); @@ -51,8 +51,8 @@ pub fn derive_ownable(input: TokenStream) -> TokenStream { // If owner is not set, only self can update the owner. // Used mostly on constructor. assert_eq!( - ::near_sdk::env::predecessor_account_id(), - ::near_sdk::env::current_account_id(), + near_sdk::env::predecessor_account_id(), + near_sdk::env::current_account_id(), "Ownable: Owner not set. Only self can set the owner" ); } @@ -64,17 +64,17 @@ pub fn derive_ownable(input: TokenStream) -> TokenStream { #cratename::events::AsEvent::emit(&event); match owner.as_ref() { - Some(owner) => ::near_sdk::env::storage_write( + Some(owner) => near_sdk::env::storage_write( &self.owner_storage_key(), owner.as_bytes(), ), - None => ::near_sdk::env::storage_remove(&self.owner_storage_key()), + None => near_sdk::env::storage_remove(&self.owner_storage_key()), }; } fn owner_is(&self) -> bool { self.owner_get().map_or(false, |owner| { - owner == ::near_sdk::env::predecessor_account_id() + owner == near_sdk::env::predecessor_account_id() }) } } @@ -103,14 +103,14 @@ pub fn only(attrs: TokenStream, item: TokenStream) -> TokenStream { let owner_check = match (contains_self, contains_owner) { (true, true) => quote! { if !self.owner_is() { - ::near_sdk::assert_self(); + near_sdk::assert_self(); } }, (true, false) => quote! { - ::near_sdk::assert_self(); + near_sdk::assert_self(); }, (false, true) => quote! { - ::near_sdk::require!(self.owner_is(), "Ownable: Method must be called from owner"); + near_sdk::require!(self.owner_is(), "Ownable: Method must be called from owner"); }, (false, false) => { // The developer did not specify a target for `only`, so we panic during macro @@ -121,5 +121,5 @@ pub fn only(attrs: TokenStream, item: TokenStream) -> TokenStream { } }; - utils::add_extra_code_to_fn(&input, owner_check) + utils::add_extra_code_to_fn(&input, &owner_check) } diff --git a/near-plugins-derive/src/pausable.rs b/near-plugins-derive/src/pausable.rs index bda149b..9c4283e 100644 --- a/near-plugins-derive/src/pausable.rs +++ b/near-plugins-derive/src/pausable.rs @@ -47,9 +47,9 @@ pub fn derive_pausable(input: TokenStream) -> TokenStream { } fn pa_all_paused(&self) -> Option> { - ::near_sdk::env::storage_read(self.pa_storage_key().as_ref()).map(|value| { + near_sdk::env::storage_read(self.pa_storage_key().as_ref()).map(|value| { std::collections::HashSet::try_from_slice(value.as_ref()) - .unwrap_or_else(|_| ::near_sdk::env::panic_str("Pausable: Invalid format for paused keys")) + .unwrap_or_else(|_| near_sdk::env::panic_str("Pausable: Invalid format for paused keys")) }) } @@ -63,15 +63,15 @@ pub fn derive_pausable(input: TokenStream) -> TokenStream { return false; } - ::near_sdk::env::storage_write( + near_sdk::env::storage_write( self.pa_storage_key().as_ref(), - ::near_sdk::borsh::to_vec(&paused_keys) - .unwrap_or_else(|_| ::near_sdk::env::panic_str("Pausable: Unexpected error serializing keys")) + near_sdk::borsh::to_vec(&paused_keys) + .unwrap_or_else(|_| near_sdk::env::panic_str("Pausable: Unexpected error serializing keys")) .as_ref(), ); let event = #cratename::pausable::Pause { - by: ::near_sdk::env::predecessor_account_id(), + by: near_sdk::env::predecessor_account_id(), key, }; #cratename::events::AsEvent::emit(&event); @@ -91,18 +91,18 @@ pub fn derive_pausable(input: TokenStream) -> TokenStream { } if paused_keys.is_empty() { - ::near_sdk::env::storage_remove(self.pa_storage_key().as_ref()); + near_sdk::env::storage_remove(self.pa_storage_key().as_ref()); } else { - ::near_sdk::env::storage_write( + near_sdk::env::storage_write( self.pa_storage_key().as_ref(), - ::near_sdk::borsh::to_vec(&paused_keys) - .unwrap_or_else(|_| ::near_sdk::env::panic_str("Pausable: Unexpected error serializing keys")) + near_sdk::borsh::to_vec(&paused_keys) + .unwrap_or_else(|_| near_sdk::env::panic_str("Pausable: Unexpected error serializing keys")) .as_ref(), ); } let event = #cratename::pausable::Unpause { - by: ::near_sdk::env::predecessor_account_id(), + by: near_sdk::env::predecessor_account_id(), key, }; #cratename::events::AsEvent::emit(&event); @@ -152,11 +152,11 @@ pub fn pause(attrs: TokenStream, item: TokenStream) -> TokenStream { let mut __check_paused = true; #bypass_condition if __check_paused { - ::near_sdk::require!(!self.pa_is_paused(#fn_name.to_string()), "Pausable: Method is paused"); + near_sdk::require!(!self.pa_is_paused(#fn_name.to_string()), "Pausable: Method is paused"); } ); - utils::add_extra_code_to_fn(&input, check_pause) + utils::add_extra_code_to_fn(&input, &check_pause) } /// Defines attributes for the `if_paused` macro. @@ -190,14 +190,14 @@ pub fn if_paused(attrs: TokenStream, item: TokenStream) -> TokenStream { let mut __check_paused = true; #bypass_condition if __check_paused { - ::near_sdk::require!( + near_sdk::require!( self.pa_is_paused(#fn_name.to_string()), #err_feature_not_paused, ); } ); - utils::add_extra_code_to_fn(&input, check_pause) + utils::add_extra_code_to_fn(&input, &check_pause) } fn get_bypass_condition(args: &ExceptSubArgs) -> proc_macro2::TokenStream { @@ -207,7 +207,7 @@ fn get_bypass_condition(args: &ExceptSubArgs) -> proc_macro2::TokenStream { let __except_roles: Vec = __except_roles.iter().map(|&x| x.into()).collect(); let may_bypass = self.acl_has_any_role( __except_roles, - ::near_sdk::env::predecessor_account_id() + near_sdk::env::predecessor_account_id() ); if may_bypass { __check_paused = false; diff --git a/near-plugins-derive/src/upgradable.rs b/near-plugins-derive/src/upgradable.rs index f42cb5b..76bf91e 100644 --- a/near-plugins-derive/src/upgradable.rs +++ b/near-plugins-derive/src/upgradable.rs @@ -58,8 +58,7 @@ impl AccessControlRoles { ); assert!( missing_roles.is_empty(), - "Specify access_control_roles for: {:?}", - missing_roles, + "Specify access_control_roles for: {missing_roles:?}", ); } } @@ -92,7 +91,7 @@ pub fn derive_upgradable(input: TokenStream) -> TokenStream { /// Used to make storage prefixes unique. Not to be used directly, /// instead it should be prepended to the storage prefix specified by /// the user. - #[derive(::near_sdk::borsh::BorshSerialize)] + #[derive(near_sdk::borsh::BorshSerialize)] #[borsh(crate = "near_sdk::borsh")] enum __UpgradableStorageKey { Code, @@ -103,42 +102,42 @@ pub fn derive_upgradable(input: TokenStream) -> TokenStream { } impl #ident { - fn up_get_timestamp(&self, key: __UpgradableStorageKey) -> Option<::near_sdk::Timestamp> { + fn up_get_timestamp(&self, key: __UpgradableStorageKey) -> Option { near_sdk::env::storage_read(self.up_storage_key(key).as_ref()).map(|timestamp_bytes| { - ::near_sdk::Timestamp::try_from_slice(×tamp_bytes).unwrap_or_else(|_| + near_sdk::Timestamp::try_from_slice(×tamp_bytes).unwrap_or_else(|_| near_sdk::env::panic_str("Upgradable: Invalid u64 timestamp format") ) }) } - fn up_get_duration(&self, key: __UpgradableStorageKey) -> Option<::near_sdk::Duration> { - ::near_sdk::env::storage_read(self.up_storage_key(key).as_ref()).map(|duration_bytes| { - ::near_sdk::Duration::try_from_slice(&duration_bytes).unwrap_or_else(|_| + fn up_get_duration(&self, key: __UpgradableStorageKey) -> Option { + near_sdk::env::storage_read(self.up_storage_key(key).as_ref()).map(|duration_bytes| { + near_sdk::Duration::try_from_slice(&duration_bytes).unwrap_or_else(|_| near_sdk::env::panic_str("Upgradable: Invalid u64 Duration format") ) }) } - fn up_set_timestamp(&self, key: __UpgradableStorageKey, value: ::near_sdk::Timestamp) { - self.up_storage_write(key, &::near_sdk::borsh::to_vec(&value).unwrap()); + fn up_set_timestamp(&self, key: __UpgradableStorageKey, value: near_sdk::Timestamp) { + self.up_storage_write(key, &near_sdk::borsh::to_vec(&value).unwrap()); } - fn up_set_duration(&self, key: __UpgradableStorageKey, value: ::near_sdk::Duration) { - self.up_storage_write(key, &::near_sdk::borsh::to_vec(&value).unwrap()); + fn up_set_duration(&self, key: __UpgradableStorageKey, value: near_sdk::Duration) { + self.up_storage_write(key, &near_sdk::borsh::to_vec(&value).unwrap()); } fn up_storage_key(&self, key: __UpgradableStorageKey) -> Vec { - let key_vec = ::near_sdk::borsh::to_vec(&key) - .unwrap_or_else(|_| ::near_sdk::env::panic_str("Storage key should be serializable")); + let key_vec = near_sdk::borsh::to_vec(&key) + .unwrap_or_else(|_| near_sdk::env::panic_str("Storage key should be serializable")); [(#storage_prefix).as_bytes(), key_vec.as_slice()].concat() } fn up_storage_write(&self, key: __UpgradableStorageKey, value: &[u8]) { - ::near_sdk::env::storage_write(self.up_storage_key(key).as_ref(), &value); + near_sdk::env::storage_write(self.up_storage_key(key).as_ref(), &value); } fn up_set_staging_duration_unchecked(&self, staging_duration: near_sdk::Duration) { - self.up_storage_write(__UpgradableStorageKey::StagingDuration, &::near_sdk::borsh::to_vec(&staging_duration).unwrap()); + self.up_storage_write(__UpgradableStorageKey::StagingDuration, &near_sdk::borsh::to_vec(&staging_duration).unwrap()); } } @@ -160,10 +159,10 @@ pub fn derive_upgradable(input: TokenStream) -> TokenStream { #[#cratename::access_control_any(roles(#(#acl_roles_code_stagers),*))] fn up_stage_code(&mut self, #[serializer(borsh)] code: Vec) { if code.is_empty() { - ::near_sdk::env::storage_remove(self.up_storage_key(__UpgradableStorageKey::Code).as_ref()); - ::near_sdk::env::storage_remove(self.up_storage_key(__UpgradableStorageKey::StagingTimestamp).as_ref()); + near_sdk::env::storage_remove(self.up_storage_key(__UpgradableStorageKey::Code).as_ref()); + near_sdk::env::storage_remove(self.up_storage_key(__UpgradableStorageKey::StagingTimestamp).as_ref()); } else { - let timestamp = ::near_sdk::env::block_timestamp() + self.up_get_duration(__UpgradableStorageKey::StagingDuration).unwrap_or(0); + let timestamp = near_sdk::env::block_timestamp() + self.up_get_duration(__UpgradableStorageKey::StagingDuration).unwrap_or(0); self.up_storage_write(__UpgradableStorageKey::Code, &code); self.up_set_timestamp(__UpgradableStorageKey::StagingTimestamp, timestamp); } @@ -171,21 +170,21 @@ pub fn derive_upgradable(input: TokenStream) -> TokenStream { #[result_serializer(borsh)] fn up_staged_code(&self) -> Option> { - ::near_sdk::env::storage_read(self.up_storage_key(__UpgradableStorageKey::Code).as_ref()) + near_sdk::env::storage_read(self.up_storage_key(__UpgradableStorageKey::Code).as_ref()) } - fn up_staged_code_hash(&self) -> Option<::near_sdk::CryptoHash> { + fn up_staged_code_hash(&self) -> Option { self.up_staged_code() - .map(|code| std::convert::TryInto::try_into(::near_sdk::env::sha256(code.as_ref())).unwrap()) + .map(|code| std::convert::TryInto::try_into(near_sdk::env::sha256(code.as_ref())).unwrap()) } #[#cratename::access_control_any(roles(#(#acl_roles_code_deployers),*))] fn up_deploy_code(&mut self, function_call_args: Option<#cratename::upgradable::FunctionCallArgs>) -> near_sdk::Promise { let staging_timestamp = self.up_get_timestamp(__UpgradableStorageKey::StagingTimestamp) - .unwrap_or_else(|| ::near_sdk::env::panic_str("Upgradable: staging timestamp isn't set")); + .unwrap_or_else(|| near_sdk::env::panic_str("Upgradable: staging timestamp isn't set")); - if ::near_sdk::env::block_timestamp() < staging_timestamp { - ::near_sdk::env::panic_str( + if near_sdk::env::block_timestamp() < staging_timestamp { + near_sdk::env::panic_str( format!( "Upgradable: Deploy code too early: staging ends on {}", staging_timestamp @@ -194,8 +193,8 @@ pub fn derive_upgradable(input: TokenStream) -> TokenStream { ); } - let code = self.up_staged_code().unwrap_or_else(|| ::near_sdk::env::panic_str("Upgradable: No staged code")); - let promise = ::near_sdk::Promise::new(::near_sdk::env::current_account_id()) + let code = self.up_staged_code().unwrap_or_else(|| near_sdk::env::panic_str("Upgradable: No staged code")); + let promise = near_sdk::Promise::new(near_sdk::env::current_account_id()) .deploy_contract(code); match function_call_args { None => promise, @@ -209,28 +208,28 @@ pub fn derive_upgradable(input: TokenStream) -> TokenStream { } #[#cratename::access_control_any(roles(#(#acl_roles_duration_initializers),*))] - fn up_init_staging_duration(&mut self, staging_duration: ::near_sdk::Duration) { - ::near_sdk::require!(self.up_get_duration(__UpgradableStorageKey::StagingDuration).is_none(), "Upgradable: staging duration was already initialized"); + fn up_init_staging_duration(&mut self, staging_duration: near_sdk::Duration) { + near_sdk::require!(self.up_get_duration(__UpgradableStorageKey::StagingDuration).is_none(), "Upgradable: staging duration was already initialized"); self.up_set_staging_duration_unchecked(staging_duration); } #[#cratename::access_control_any(roles(#(#acl_roles_duration_update_stagers),*))] - fn up_stage_update_staging_duration(&mut self, staging_duration: ::near_sdk::Duration) { + fn up_stage_update_staging_duration(&mut self, staging_duration: near_sdk::Duration) { let current_staging_duration = self.up_get_duration(__UpgradableStorageKey::StagingDuration) - .unwrap_or_else(|| ::near_sdk::env::panic_str("Upgradable: staging duration isn't initialized")); + .unwrap_or_else(|| near_sdk::env::panic_str("Upgradable: staging duration isn't initialized")); self.up_set_duration(__UpgradableStorageKey::NewStagingDuration, staging_duration); - let staging_duration_timestamp = ::near_sdk::env::block_timestamp() + current_staging_duration; + let staging_duration_timestamp = near_sdk::env::block_timestamp() + current_staging_duration; self.up_set_timestamp(__UpgradableStorageKey::NewStagingDurationTimestamp, staging_duration_timestamp); } #[#cratename::access_control_any(roles(#(#acl_roles_duration_update_appliers),*))] fn up_apply_update_staging_duration(&mut self) { let staging_timestamp = self.up_get_timestamp(__UpgradableStorageKey::NewStagingDurationTimestamp) - .unwrap_or_else(|| ::near_sdk::env::panic_str("Upgradable: No staged update")); + .unwrap_or_else(|| near_sdk::env::panic_str("Upgradable: No staged update")); - if ::near_sdk::env::block_timestamp() < staging_timestamp { - ::near_sdk::env::panic_str( + if near_sdk::env::block_timestamp() < staging_timestamp { + near_sdk::env::panic_str( format!( "Upgradable: Update duration too early: staging ends on {}", staging_timestamp @@ -240,7 +239,7 @@ pub fn derive_upgradable(input: TokenStream) -> TokenStream { } let new_duration = self.up_get_duration(__UpgradableStorageKey::NewStagingDuration) - .unwrap_or_else(|| ::near_sdk::env::panic_str("Upgradable: No staged duration update")); + .unwrap_or_else(|| near_sdk::env::panic_str("Upgradable: No staged duration update")); self.up_set_duration(__UpgradableStorageKey::StagingDuration, new_duration); } diff --git a/near-plugins-derive/src/utils.rs b/near-plugins-derive/src/utils.rs index b9f14cc..228aedb 100644 --- a/near-plugins-derive/src/utils.rs +++ b/near-plugins-derive/src/utils.rs @@ -3,11 +3,11 @@ use proc_macro_crate::crate_name; use syn::{Ident, ItemFn}; /// Determines if this block of code was [generated by near_bindgen]. -/// Heuristic used is to check for #[no_mangle]. +/// Heuristic used is to check for `#[no_mangle]`. /// TODO: How to make this 100% safe. Discuss with near-sdk team /// /// [generated by near_bindgen]: https://github.com/near/near-sdk-rs/issues/722 -pub(crate) fn is_near_bindgen_wrapped_or_marshall(item: &ItemFn) -> bool { +pub fn is_near_bindgen_wrapped_or_marshall(item: &ItemFn) -> bool { let pattern1 = "(target_arch = \"wasm32\")"; let pattern2 = "(not(target_arch = \"wasm32\"))"; item.attrs.iter().any(|attr| { @@ -17,7 +17,7 @@ pub(crate) fn is_near_bindgen_wrapped_or_marshall(item: &ItemFn) -> bool { } /// Returns an identifier for the name of the crate which is imported by plugin users. -pub(crate) fn cratename() -> Ident { +pub fn cratename() -> Ident { Ident::new( &crate_name("near-plugins").unwrap_or_else(|_| "near_plugins".to_string()), Span::call_site(), @@ -25,9 +25,9 @@ pub(crate) fn cratename() -> Ident { } /// Injects extra code into a function. -pub(crate) fn add_extra_code_to_fn( +pub fn add_extra_code_to_fn( fn_code: &ItemFn, - extra_code: proc_macro2::TokenStream, + extra_code: &proc_macro2::TokenStream, ) -> proc_macro::TokenStream { let ItemFn { attrs, diff --git a/near-plugins-derive/tests/access_controllable.rs b/near-plugins-derive/tests/access_controllable.rs index 9224843..afe39bb 100644 --- a/near-plugins-derive/tests/access_controllable.rs +++ b/near-plugins-derive/tests/access_controllable.rs @@ -39,7 +39,7 @@ impl Setup { /// Deploys the contract and calls the initialization method without passing any accounts to be /// added as admin or grantees. async fn new() -> anyhow::Result { - Self::new_with_admins_and_grantees(Default::default(), Default::default()).await + Self::new_with_admins_and_grantees(HashMap::default(), HashMap::default()).await } /// Deploys the contract with a specific wasm binary. @@ -175,21 +175,21 @@ fn assert_permissioned_account_equivalence(a: &PermissionedAccounts, b: &Permiss let per_role_a = a .roles .get(role) - .unwrap_or_else(|| panic!("PermissionedAccounts a misses role {}", role)); + .unwrap_or_else(|| panic!("PermissionedAccounts a misses role {role}")); let per_role_b = b .roles .get(role) - .unwrap_or_else(|| panic!("PermissionedAccounts b misses role {}", role)); + .unwrap_or_else(|| panic!("PermissionedAccounts b misses role {role}")); assert_account_ids_equivalence( &per_role_a.admins, &per_role_b.admins, - format!("admins of role {}", role).as_str(), + &format!("admins of role {role}"), ); assert_account_ids_equivalence( &per_role_a.grantees, &per_role_b.grantees, - format!("grantees of role {}", role).as_str(), + &format!("grantees of role {role}"), ); } } @@ -206,7 +206,7 @@ fn assert_account_ids_equivalence( ) { let set_a: HashSet<_> = a.iter().cloned().collect(); let set_b: HashSet<_> = b.iter().cloned().collect(); - assert_eq!(set_a, set_b, "Unequal sets of AccountIds for {}", specifier,); + assert_eq!(set_a, set_b, "Unequal sets of AccountIds for {specifier}"); } /// Smoke test of contract setup and basic functionality. @@ -916,6 +916,7 @@ async fn test_acl_has_role() -> anyhow::Result<()> { } #[tokio::test] +#[allow(clippy::similar_names)] async fn test_acl_grant_role() -> anyhow::Result<()> { let Setup { worker, @@ -1134,20 +1135,20 @@ async fn test_attribute_access_control_any() -> anyhow::Result<()> { // Account without any of the required permissions is restricted. let account = setup.new_account_with_roles(&[]).await?; let res = call_increase_2(raw_contract, &account).await?; - assert_insufficient_acl_permissions(res, method_name, allowed_roles.clone()); + assert_insufficient_acl_permissions(res, method_name, &allowed_roles); let account = setup.new_account_with_roles(&["Resetter"]).await?; let res = call_increase_2(raw_contract, &account).await?; - assert_insufficient_acl_permissions(res, method_name, allowed_roles.clone()); + assert_insufficient_acl_permissions(res, method_name, &allowed_roles); // A super-admin which has not been granted the role is restricted. let super_admin = setup.new_super_admin_account().await?; let res = call_increase_2(raw_contract, &super_admin).await?; - assert_insufficient_acl_permissions(res, method_name, allowed_roles.clone()); + assert_insufficient_acl_permissions(res, method_name, &allowed_roles); // An admin for a permitted role is restricted (no grantee of role itself). let admin = setup.new_account_as_admin(&["ByMax2Increaser"]).await?; let res = call_increase_2(raw_contract, &admin).await?; - assert_insufficient_acl_permissions(res, method_name, allowed_roles.clone()); + assert_insufficient_acl_permissions(res, method_name, &allowed_roles); // Account with one of the required permissions succeeds. let account = setup.new_account_with_roles(&["ByMax2Increaser"]).await?; @@ -1224,8 +1225,8 @@ async fn test_acl_get_super_admins() -> anyhow::Result<()> { .acl_get_super_admins(&setup.account, i, 1) .await?; let i = usize::try_from(i).unwrap(); - let expected = super_admin_ids[i..i + 1].to_vec(); - assert_eq!(actual, expected, "Mismatch at position {}", i,); + let expected = super_admin_ids[i..=i].to_vec(); + assert_eq!(actual, expected, "Mismatch at position {i}"); } // Retrieve super-admins with step size 2. @@ -1295,8 +1296,8 @@ async fn test_acl_get_admins() -> anyhow::Result<()> { .acl_get_admins(&setup.account, role, i, 1) .await?; let i = usize::try_from(i).unwrap(); - let expected = admin_ids[i..i + 1].to_vec(); - assert_eq!(actual, expected, "Mismatch at position {}", i,); + let expected = admin_ids[i..=i].to_vec(); + assert_eq!(actual, expected, "Mismatch at position {i}"); } // Retrieve admins with step size 2. @@ -1366,8 +1367,8 @@ async fn test_acl_get_grantees() -> anyhow::Result<()> { .acl_get_grantees(&setup.account, role, i, 1) .await?; let i = usize::try_from(i).unwrap(); - let expected = grantee_ids[i..i + 1].to_vec(); - assert_eq!(actual, expected, "Mismatch at position {}", i,); + let expected = grantee_ids[i..=i].to_vec(); + assert_eq!(actual, expected, "Mismatch at position {i}"); } // Retrieve grantees with step size 2. diff --git a/near-plugins-derive/tests/common/access_controllable_contract.rs b/near-plugins-derive/tests/common/access_controllable_contract.rs index 6e8c1e5..38ee31f 100644 --- a/near-plugins-derive/tests/common/access_controllable_contract.rs +++ b/near-plugins-derive/tests/common/access_controllable_contract.rs @@ -11,11 +11,13 @@ pub struct AccessControllableContract { } impl AccessControllableContract { - pub fn new(contract: Contract) -> Self { + #[must_use] + pub const fn new(contract: Contract) -> Self { Self { contract } } - pub fn contract(&self) -> &Contract { + #[must_use] + pub const fn contract(&self) -> &Contract { &self.contract } diff --git a/near-plugins-derive/tests/common/ownable_contract.rs b/near-plugins-derive/tests/common/ownable_contract.rs index 723601c..b05100b 100644 --- a/near-plugins-derive/tests/common/ownable_contract.rs +++ b/near-plugins-derive/tests/common/ownable_contract.rs @@ -9,11 +9,13 @@ pub struct OwnableContract { } impl OwnableContract { - pub fn new(contract: Contract) -> Self { + #[must_use] + pub const fn new(contract: Contract) -> Self { Self { contract } } - pub fn contract(&self) -> &Contract { + #[must_use] + pub const fn contract(&self) -> &Contract { &self.contract } diff --git a/near-plugins-derive/tests/common/pausable_contract.rs b/near-plugins-derive/tests/common/pausable_contract.rs index 6c9c3fa..d387a7a 100644 --- a/near-plugins-derive/tests/common/pausable_contract.rs +++ b/near-plugins-derive/tests/common/pausable_contract.rs @@ -10,11 +10,13 @@ pub struct PausableContract { } impl PausableContract { - pub fn new(contract: Contract) -> Self { + #[must_use] + pub const fn new(contract: Contract) -> Self { Self { contract } } - pub fn contract(&self) -> &Contract { + #[must_use] + pub const fn contract(&self) -> &Contract { &self.contract } diff --git a/near-plugins-derive/tests/common/repo.rs b/near-plugins-derive/tests/common/repo.rs index 2f52b94..2628ec8 100644 --- a/near-plugins-derive/tests/common/repo.rs +++ b/near-plugins-derive/tests/common/repo.rs @@ -15,11 +15,11 @@ async fn read_toolchain(project_path: &Path) -> anyhow::Result { Ok(result) } -pub fn require_success(output: Output) -> Result<(), anyhow::Error> { +pub fn require_success(output: &Output) -> Result<(), anyhow::Error> { if output.status.success() { Ok(()) } else { - Err(anyhow::Error::msg(format!("Command failed: {:?}", output))) + Err(anyhow::Error::msg(format!("Command failed: {output:?}"))) } } @@ -30,7 +30,7 @@ async fn add_wasm_target(project_path: &Path, toolchain: &str) -> anyhow::Result .args(["target", "add", "wasm32-unknown-unknown"]) .output() .await?; - require_success(output)?; + require_success(&output)?; Ok(()) } @@ -52,13 +52,13 @@ pub async fn compile_project(project_path: &Path, package_name: &str) -> anyhow: .output() .await?; - require_success(output)?; + require_success(&output)?; let binary_path = project_path.join( [ "target", "wasm32-unknown-unknown", "release", - format!("{}.wasm", package_name).as_str(), + format!("{package_name}.wasm").as_str(), ] .iter() .collect::(), diff --git a/near-plugins-derive/tests/common/upgradable_contract.rs b/near-plugins-derive/tests/common/upgradable_contract.rs index 999e10d..d3c2b50 100644 --- a/near-plugins-derive/tests/common/upgradable_contract.rs +++ b/near-plugins-derive/tests/common/upgradable_contract.rs @@ -13,11 +13,13 @@ pub struct UpgradableContract { } impl UpgradableContract { - pub fn new(contract: Contract) -> Self { + #[must_use] + pub const fn new(contract: Contract) -> Self { Self { contract } } - pub fn contract(&self) -> &Contract { + #[must_use] + pub const fn contract(&self) -> &Contract { &self.contract } diff --git a/near-plugins-derive/tests/common/utils.rs b/near-plugins-derive/tests/common/utils.rs index 2fb95a9..d9f62fa 100644 --- a/near-plugins-derive/tests/common/utils.rs +++ b/near-plugins-derive/tests/common/utils.rs @@ -10,12 +10,14 @@ use std::str::FromStr; /// Converts `account_id` to a `near_sdk::AccountId` and panics on failure. /// /// Only available in tests, hence favoring simplicity over efficiency. +#[must_use] pub fn as_sdk_account_id(account_id: &AccountId) -> near_sdk::AccountId { near_sdk::AccountId::from_str(account_id.as_str()) .expect("Conversion to near_sdk::AccountId should succeed") } /// Convenience function to create a new `near_sdk::Duration`. Panics if the conversion fails. +#[must_use] pub fn sdk_duration_from_secs(seconds: u64) -> Duration { std::time::Duration::from_secs(seconds) .as_nanos() @@ -39,7 +41,7 @@ pub fn assert_success_with_unit_return(res: ExecutionFinalResult) { /// Asserts execution was successful and returned the `expected` value. pub fn assert_success_with(res: ExecutionFinalResult, expected: T) where - T: DeserializeOwned + PartialEq + Debug, + T: DeserializeOwned + PartialEq + Debug + Copy, { let actual = res .into_result() @@ -59,13 +61,11 @@ pub fn assert_private_method_failure(res: ExecutionFinalResult, method: &str) { let err = res .into_result() .expect_err("Transaction should have failed"); - let err = format!("{}", err); - let must_contain = format!("Method {} is private", method); + let err = format!("{err}"); + let must_contain = format!("Method {method} is private"); assert!( err.contains(&must_contain), - "'{}' is not contained in '{}'", - must_contain, - err, + "'{must_contain}' is not contained in '{err}'", ); } @@ -74,26 +74,22 @@ pub fn assert_private_method_failure(res: ExecutionFinalResult, method: &str) { pub fn assert_insufficient_acl_permissions( res: ExecutionFinalResult, method: &str, - _allowed_roles: Vec, + _allowed_roles: &[String], ) { let err = res .into_result() .expect_err("Transaction should have failed"); - let err = format!("{}", err); + let err = format!("{err}"); // TODO fix escaping issue to also verify second sentence of the error // Using `format!` here it'll be: Requires one of these roles: ["LevelA", "LevelB"] // However, roles contained in `err` are escaped, i.e. [\"LevelA\", \"LevelB\"] - let must_contain = format!( - "Insufficient permissions for method {} restricted by access control.", - method, - ); + let must_contain = + format!("Insufficient permissions for method {method} restricted by access control."); assert!( err.contains(&must_contain), - "'{}' is not contained in '{}'", - must_contain, - err, + "'{must_contain}' is not contained in '{err}'", ); } @@ -101,12 +97,11 @@ pub fn assert_method_is_paused(res: ExecutionFinalResult) { let err = res .into_result() .expect_err("Transaction should have failed"); - let err = format!("{}", err); + let err = format!("{err}"); let must_contain = "Pausable: Method is paused"; assert!( err.contains(must_contain), - "Expected method to be paused, instead it failed with: {}", - err + "Expected method to be paused, instead it failed with: {err}" ); } @@ -119,12 +114,11 @@ pub fn assert_owner_update_failure(res: ExecutionFinalResult) { let err = res .into_result() .expect_err("Transaction should have failed"); - let err = format!("{}", err); + let err = format!("{err}"); let must_contain = "Ownable: Only owner can update current owner"; assert!( err.contains(must_contain), - "Expected failure due to caller not being owner, instead it failed with: {}", - err + "Expected failure due to caller not being owner, instead it failed with: {err}" ); } @@ -133,12 +127,11 @@ pub fn assert_ownable_permission_failure(res: ExecutionFinalResult) { let err = res .into_result() .expect_err("Transaction should have failed"); - let err = format!("{}", err); + let err = format!("{err}"); let must_contain = "Method is private"; assert!( err.contains(must_contain), - "Expected failure due to insufficient permissions, instead it failed with: {}", - err + "Expected failure due to insufficient permissions, instead it failed with: {err}" ); } @@ -148,12 +141,11 @@ pub fn assert_only_owner_permission_failure(res: ExecutionFinalResult) { let err = res .into_result() .expect_err("Transaction should have failed"); - let err = format!("{}", err); + let err = format!("{err}"); let must_contain = "Ownable: Method must be called from owner"; assert!( err.contains(must_contain), - "Expected failure due to caller not being owner, instead it failed with: {}", - err + "Expected failure due to caller not being owner, instead it failed with: {err}" ); } @@ -162,12 +154,10 @@ pub fn assert_failure_with(res: ExecutionFinalResult, must_contain: &str) { let err = res .into_result() .expect_err("Transaction should have failed"); - let err = format!("{}", err); + let err = format!("{err}"); assert!( err.contains(must_contain), - "The expected message\n'{}'\nis not contained in error\n'{}'", - must_contain, - err, + "The expected message\n'{must_contain}'\nis not contained in error\n'{err}'" ); } @@ -177,15 +167,13 @@ pub fn assert_access_key_not_found_error( let err = res.expect_err("Transaction should not have been executed"); // Debug formatting is required to get the full error message containing `AccessKeyNotFound`. - // Assume that is acceptable since this function is avaible only in tests. - let err = format!("{:?}", err); + // Assume that is acceptable since this function is available only in tests. + let err = format!("{err:?}"); let must_contain = "InvalidAccessKeyError"; assert!( err.contains(must_contain), - "The expected message\n'{}'\nis not contained in error\n'{}'", - must_contain, - err, + "The expected message\n'{must_contain}'\nis not contained in error\n'{err}'" ); } diff --git a/near-plugins-derive/tests/contracts/access_controllable/Cargo.toml b/near-plugins-derive/tests/contracts/access_controllable/Cargo.toml index ac57551..3b7837d 100644 --- a/near-plugins-derive/tests/contracts/access_controllable/Cargo.toml +++ b/near-plugins-derive/tests/contracts/access_controllable/Cargo.toml @@ -17,5 +17,6 @@ lto = true debug = false panic = "abort" overflow-checks = true +strip = "symbols" [workspace] diff --git a/near-plugins-derive/tests/contracts/ownable/Cargo.toml b/near-plugins-derive/tests/contracts/ownable/Cargo.toml index deb2cce..94a647f 100644 --- a/near-plugins-derive/tests/contracts/ownable/Cargo.toml +++ b/near-plugins-derive/tests/contracts/ownable/Cargo.toml @@ -17,5 +17,6 @@ lto = true debug = false panic = "abort" overflow-checks = true +strip = "symbols" [workspace] diff --git a/near-plugins-derive/tests/contracts/pausable/Cargo.toml b/near-plugins-derive/tests/contracts/pausable/Cargo.toml index 3b417ed..1c8758b 100644 --- a/near-plugins-derive/tests/contracts/pausable/Cargo.toml +++ b/near-plugins-derive/tests/contracts/pausable/Cargo.toml @@ -17,5 +17,6 @@ lto = true debug = false panic = "abort" overflow-checks = true +strip = "symbols" [workspace] diff --git a/near-plugins-derive/tests/contracts/upgradable/Cargo.toml b/near-plugins-derive/tests/contracts/upgradable/Cargo.toml index 39b051d..5c44272 100644 --- a/near-plugins-derive/tests/contracts/upgradable/Cargo.toml +++ b/near-plugins-derive/tests/contracts/upgradable/Cargo.toml @@ -17,5 +17,6 @@ lto = true debug = false panic = "abort" overflow-checks = true +strip = "symbols" [workspace] diff --git a/near-plugins-derive/tests/contracts/upgradable_2/Cargo.toml b/near-plugins-derive/tests/contracts/upgradable_2/Cargo.toml index d35a907..e2d34a0 100644 --- a/near-plugins-derive/tests/contracts/upgradable_2/Cargo.toml +++ b/near-plugins-derive/tests/contracts/upgradable_2/Cargo.toml @@ -17,5 +17,6 @@ lto = true debug = false panic = "abort" overflow-checks = true +strip = "symbols" [workspace] diff --git a/near-plugins-derive/tests/contracts/upgradable_state_migration/Cargo.toml b/near-plugins-derive/tests/contracts/upgradable_state_migration/Cargo.toml index 0fd04d9..d112d41 100644 --- a/near-plugins-derive/tests/contracts/upgradable_state_migration/Cargo.toml +++ b/near-plugins-derive/tests/contracts/upgradable_state_migration/Cargo.toml @@ -17,5 +17,6 @@ lto = true debug = false panic = "abort" overflow-checks = true +strip = "symbols" [workspace] diff --git a/near-plugins-derive/tests/pausable.rs b/near-plugins-derive/tests/pausable.rs index 6f5604a..3ae33e1 100644 --- a/near-plugins-derive/tests/pausable.rs +++ b/near-plugins-derive/tests/pausable.rs @@ -177,11 +177,7 @@ async fn assert_pause_feature_acl_failure(contract: &PausableContract, caller: & .pa_pause_feature(caller, "increase_1") .await .unwrap(); - assert_insufficient_acl_permissions( - result, - "pa_pause_feature", - vec!["PauseManager".to_string()], - ); + assert_insufficient_acl_permissions(result, "pa_pause_feature", &["PauseManager".to_string()]); } #[tokio::test] @@ -257,7 +253,7 @@ async fn assert_unpause_feature_acl_failure(contract: &PausableContract, caller: assert_insufficient_acl_permissions( result, "pa_unpause_feature", - vec!["PauseManager".to_string()], + &["PauseManager".to_string()], ); } diff --git a/near-plugins-derive/tests/upgradable.rs b/near-plugins-derive/tests/upgradable.rs index 101ec48..f4ae534 100644 --- a/near-plugins-derive/tests/upgradable.rs +++ b/near-plugins-derive/tests/upgradable.rs @@ -240,7 +240,7 @@ async fn test_stage_code_permission_failure() -> anyhow::Result<()> { assert_insufficient_acl_permissions( res, "up_stage_code", - vec!["CodeStager".to_string(), "DAO".to_string()], + &["CodeStager".to_string(), "DAO".to_string()], ); // Verify no code was staged. @@ -627,7 +627,7 @@ async fn test_deploy_code_in_batch_transaction_pitfall() -> anyhow::Result<()> { .get(1) .expect("There should be at least two receipts"); assert!(fn_call_deploy_receipt.is_failure()); - assert!(format!("{:?}", fn_call_deploy_receipt).contains("Failing migration on purpose")); + assert!(format!("{fn_call_deploy_receipt:?}").contains("Failing migration on purpose")); // Verify `code` wasn't deployed by calling a function that is defined only in the initial // contract but not in the contract corresponding to `code`. @@ -728,7 +728,7 @@ async fn test_deploy_code_permission_failure() -> anyhow::Result<()> { assert_insufficient_acl_permissions( res, "up_deploy_code", - vec!["CodeDeployer".to_string(), "DAO".to_string()], + &["CodeDeployer".to_string(), "DAO".to_string()], ); // Verify `code` wasn't deployed by calling a function that is defined only in the initial @@ -783,7 +783,7 @@ async fn test_init_staging_duration_permission_failure() -> anyhow::Result<()> { assert_insufficient_acl_permissions( res, "up_init_staging_duration", - vec!["DurationManager".to_string(), "DAO".to_string()], + &["DurationManager".to_string(), "DAO".to_string()], ); setup.assert_staging_duration(None).await; @@ -830,7 +830,7 @@ async fn test_stage_update_staging_duration_permission_failure() -> anyhow::Resu assert_insufficient_acl_permissions( res, "up_stage_update_staging_duration", - vec!["DurationManager".to_string(), "DAO".to_string()], + &["DurationManager".to_string(), "DAO".to_string()], ); // Verify no duration was staged. @@ -904,7 +904,7 @@ async fn test_apply_update_staging_duration_permission_failure() -> anyhow::Resu assert_insufficient_acl_permissions( res, "up_apply_update_staging_duration", - vec!["DurationManager".to_string(), "DAO".to_string()], + &["DurationManager".to_string(), "DAO".to_string()], ); // Verify the update was not applied. @@ -1015,7 +1015,7 @@ async fn test_acl_permission_scope() -> anyhow::Result<()> { assert_insufficient_acl_permissions( res, "up_deploy_code", - vec!["CodeDeployer".to_string(), "DAO".to_string()], + &["CodeDeployer".to_string(), "DAO".to_string()], ); // Verify `code` wasn't deployed by calling a function that is defined only in the initial diff --git a/near-plugins/Cargo.toml b/near-plugins/Cargo.toml index c316c9d..c6d56aa 100644 --- a/near-plugins/Cargo.toml +++ b/near-plugins/Cargo.toml @@ -16,3 +16,6 @@ serde.workspace = true [dev-dependencies] near-sdk = { workspace = true, features = ["unit-testing"] } + +[lints] +workspace = true diff --git a/near-plugins/src/access_controllable.rs b/near-plugins/src/access_controllable.rs index c1da319..5b89c1e 100644 --- a/near-plugins/src/access_controllable.rs +++ b/near-plugins/src/access_controllable.rs @@ -13,7 +13,7 @@ //! //! Using the `#[access_control_any(roles(...))]` macro on a contract method restricts access to the //! method to grantees of the specified `roles`. The method panics if it is called by an account -//! which is not a grantee of any of the `roles`. +//! which is not a grantee any of the `roles`. //! //! In addition, methods like `AccessControllable::has_role` can be used within other contract //! methods to restrict access to certain features or actions. @@ -32,7 +32,7 @@ //! //! ## Credits //! -//! Inspired by OpenZeppelin's +//! Inspired by `OpenZeppelin`'s //! [AccessControl](https://docs.openzeppelin.com/contracts/3.x/api/access#AccessControl) module. use near_sdk::serde::{Deserialize, Serialize}; @@ -55,8 +55,8 @@ use std::collections::HashMap; /// /// [does not support]: https://github.com/near/near-sdk-rs/blob/9d99077c6acfde68c06845f2a1eb2b5ed7983401/near-sdk/compilation_tests/impl_generic.stderr pub trait AccessControllable { - /// Returns the storage prefix for collections related to access control. By - /// default `b"__acl"` is used. + /// Returns the storage prefix for collections related to access control. + /// `b"__acl"` is used by default. /// /// Attribute `storage_prefix` can be used to set a different prefix: /// @@ -74,10 +74,10 @@ pub trait AccessControllable { /// A vector containing _all_ variant names is returned since the default implementation limits /// the number of variants to [`near_plugins_derive::access_control_role::MAX_ROLE_VARIANTS`]. /// This allows for a simpler user experience compared to the iterator based approach of - /// [`Self::acl_get_admins`], for example. For custom implmentations of this it is advised to + /// [`Self::acl_get_admins`], for example. For custom implementations of this it is advised to /// limit the number of role variants as well. /// - /// Event though it might not be used, this method takes paramter `&self` to be [available in + /// Event though it might not be used, this method takes parameter `&self` to be [available in /// view calls]. /// /// [available in view calls]: https://stackoverflow.com/q/66715815 @@ -193,7 +193,7 @@ pub trait AccessControllable { /// } /// } /// ``` - /// + /// /// ```json /// { /// "standard":"AccessControllable", @@ -235,7 +235,7 @@ pub trait AccessControllable { /// Returns whether `account_id` is an admin for `role`. Super-admins are /// admins for _every_ role. /// - /// Note that adding an account as admin for `role` does not make that + /// Note that adding an account as admin for `role` does not make the /// account a grantee of `role`. Instead, `role` has to be granted /// explicitly. The same applies to super-admins. fn acl_is_admin(&self, role: String, account_id: AccountId) -> bool; @@ -296,7 +296,7 @@ pub trait AccessControllable { fn acl_grant_role(&mut self, role: String, account_id: AccountId) -> Option; /// Returns whether `account_id` has been granted `role`. Note that adding - /// an account as (super-)admin for `role` does not make that account a + /// an account as (super-)admin for `role` does not make the account a /// grantee of `role`. Instead, `role` has to be granted explicitly. fn acl_has_role(&self, role: String, account_id: AccountId) -> bool; @@ -428,7 +428,7 @@ pub mod events { const STANDARD: &str = "AccessControllable"; const VERSION: &str = "1.0.0"; - /// Event emitted when an accout is made super-admin. + /// Event emitted when an account is made super-admin. #[derive(Serialize, Clone)] #[serde(crate = "near_sdk::serde")] pub struct SuperAdminAdded { @@ -438,8 +438,8 @@ pub mod events { pub by: AccountId, } - impl AsEvent for SuperAdminAdded { - fn metadata(&self) -> EventMetadata { + impl AsEvent for SuperAdminAdded { + fn metadata(&self) -> EventMetadata { EventMetadata { standard: STANDARD.to_string(), version: VERSION.to_string(), @@ -459,8 +459,8 @@ pub mod events { pub by: AccountId, } - impl AsEvent for SuperAdminRevoked { - fn metadata(&self) -> EventMetadata { + impl AsEvent for SuperAdminRevoked { + fn metadata(&self) -> EventMetadata { EventMetadata { standard: STANDARD.to_string(), version: VERSION.to_string(), @@ -482,8 +482,8 @@ pub mod events { pub by: AccountId, } - impl AsEvent for AdminAdded { - fn metadata(&self) -> EventMetadata { + impl AsEvent for AdminAdded { + fn metadata(&self) -> EventMetadata { EventMetadata { standard: STANDARD.to_string(), version: VERSION.to_string(), @@ -505,8 +505,8 @@ pub mod events { pub by: AccountId, } - impl AsEvent for AdminRevoked { - fn metadata(&self) -> EventMetadata { + impl AsEvent for AdminRevoked { + fn metadata(&self) -> EventMetadata { EventMetadata { standard: STANDARD.to_string(), version: VERSION.to_string(), @@ -528,8 +528,8 @@ pub mod events { pub by: AccountId, } - impl AsEvent for RoleGranted { - fn metadata(&self) -> EventMetadata { + impl AsEvent for RoleGranted { + fn metadata(&self) -> EventMetadata { EventMetadata { standard: STANDARD.to_string(), version: VERSION.to_string(), @@ -551,8 +551,8 @@ pub mod events { pub by: AccountId, } - impl AsEvent for RoleRevoked { - fn metadata(&self) -> EventMetadata { + impl AsEvent for RoleRevoked { + fn metadata(&self) -> EventMetadata { EventMetadata { standard: STANDARD.to_string(), version: VERSION.to_string(), diff --git a/near-plugins/src/events.rs b/near-plugins/src/events.rs index 39ceac0..e9a981c 100644 --- a/near-plugins/src/events.rs +++ b/near-plugins/src/events.rs @@ -5,7 +5,7 @@ use serde::Serialize; /// Interface to capture metadata about an event #[derive(Serialize)] -pub struct EventMetadata { +pub struct EventMetadata { /// name of standard, e.g. nep171 pub standard: String, /// e.g. 1.0.0 @@ -58,7 +58,7 @@ mod tests { /// Helper function to check if an event is well formed and follows NEP-297 /// i.e. tries to deserialize the json object. - fn valid_event(event: String) -> bool { + fn valid_event(event: &str) -> bool { #[derive(serde::Deserialize)] struct EventFormat { #[allow(dead_code)] @@ -86,7 +86,7 @@ mod tests { let expected = r#"EVENT_JSON:{"standard":"Compile","version":"0.0.1","event":"compile_test"}"#; assert_eq!(event_log, expected); - assert!(valid_event(event_log)); + assert!(valid_event(&event_log)); } #[test] @@ -97,6 +97,6 @@ mod tests { let event_log = compile_event.event(); let expected = r#"EVENT_JSON:{"standard":"Compile","version":"0.0.1","event":"compile_test","data":"Compilation successful"}"#; assert_eq!(event_log, expected); - assert!(valid_event(event_log)); + assert!(valid_event(&event_log)); } } diff --git a/near-plugins/src/ownable.rs b/near-plugins/src/ownable.rs index b394393..e612947 100644 --- a/near-plugins/src/ownable.rs +++ b/near-plugins/src/ownable.rs @@ -5,19 +5,19 @@ //! specific functions. //! //! During creation of the contract set the owner using `owner_set`. Protect functions that should -//! only be called by the owner using #[only(owner)]. +//! only be called by the owner using annotation: `#[only(owner)]`. //! //! ## Credits: //! //! Inspired by Open Zeppelin Ownable module: -//! https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol +//! `https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol` use crate::events::{AsEvent, EventMetadata}; use near_sdk::AccountId; use serde::Serialize; /// Trait describing the functionality of the _Ownable_ plugin. pub trait Ownable { - /// Returns the key of storage slot to save the current owner. By default b"__OWNER__" is used. + /// Returns the key of storage slot to save the current owner. b"__OWNER__" is used by default. /// /// Attribute `owner_storage_key` can be used to set a different key: /// @@ -76,8 +76,8 @@ pub struct OwnershipTransferred { pub new_owner: Option, } -impl AsEvent for OwnershipTransferred { - fn metadata(&self) -> EventMetadata { +impl AsEvent for OwnershipTransferred { + fn metadata(&self) -> EventMetadata { EventMetadata { standard: "Ownable".to_string(), version: "1.0.0".to_string(), diff --git a/near-plugins/src/pausable.rs b/near-plugins/src/pausable.rs index c9af043..198828e 100644 --- a/near-plugins/src/pausable.rs +++ b/near-plugins/src/pausable.rs @@ -10,10 +10,10 @@ //! ## Default implementation: //! //! Key "ALL" is understood to pause all "pausable" features at once. -//! Provided implementation is optimized for the case where only a small amount of features are -//! paused at a single moment. If all features are meant to be paused, use "ALL" instead. This is done +//! Provided implementation is optimized for the case where only a small amount of features is +//! paused at a single moment. If all features should be paused, use "ALL" instead. This is done //! by storing all paused keys in a single slot on the storage. Notice that unpausing "ALL" will not -//! necessarily unpause all features, if other features are still present in the paused_list. +//! necessarily unpause all features, if other features are still present in the `paused_list`. //! //! As a precondition for being `Pausable` a contract must be `AccessControllable`. Access control //! is used to define the permissions required to pause and unpause features. In addition, grantees @@ -23,7 +23,7 @@ //! ## Credits: //! //! Inspired by Open Zeppelin Pausable module: -//! https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/security/Pausable.sol +//! `https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/security/Pausable.sol` use crate::events::{AsEvent, EventMetadata}; use near_sdk::AccountId; use serde::Serialize; @@ -105,8 +105,8 @@ pub struct Pause { pub key: String, } -impl AsEvent for Pause { - fn metadata(&self) -> EventMetadata { +impl AsEvent for Pause { + fn metadata(&self) -> EventMetadata { EventMetadata { standard: "Pausable".to_string(), version: "1.0.0".to_string(), @@ -125,8 +125,8 @@ pub struct Unpause { pub key: String, } -impl AsEvent for Unpause { - fn metadata(&self) -> EventMetadata { +impl AsEvent for Unpause { + fn metadata(&self) -> EventMetadata { EventMetadata { standard: "Pausable".to_string(), version: "1.0.0".to_string(), diff --git a/near-plugins/src/upgradable.rs b/near-plugins/src/upgradable.rs index 1df00ad..208df66 100644 --- a/near-plugins/src/upgradable.rs +++ b/near-plugins/src/upgradable.rs @@ -112,13 +112,13 @@ pub trait Upgradable { /// Attaching a function call can be useful, for example, if deploying the staged code requires /// [state migration]. It can be achieved by calling a migration function defined in the new /// version of the contract. A failure during state migration can leave the contract in a broken - /// state, which is avoided by the roleback mechanism described above. + /// state, which is avoided by the rollback mechanism described above. /// /// # Removal of staged code /// /// After deployment, staged code remains in storage. It is not removed automatically as this /// would cost extra gas and therefore increase the risk of the transaction hitting NEAR's gas - /// limit. Moreover, in case the deployment is roled back due to a failure in the attached + /// limit. Moreover, in case the deployment is rollbacked due to a failure in the attached /// function call, the staged code might still be required. /// /// Once staged code is no longer needed, it can be removed by passing the appropriate arguments @@ -183,6 +183,7 @@ pub trait Upgradable { } #[derive(Deserialize, Serialize)] +#[allow(clippy::module_name_repetitions)] pub struct UpgradableDurationStatus { pub staging_duration: Option, pub staging_timestamp: Option, @@ -213,8 +214,8 @@ struct StageCode { code_hash: CryptoHash, } -impl AsEvent for StageCode { - fn metadata(&self) -> EventMetadata { +impl AsEvent for StageCode { + fn metadata(&self) -> EventMetadata { EventMetadata { standard: "Upgradable".to_string(), version: "1.0.0".to_string(), @@ -233,8 +234,8 @@ struct DeployCode { code_hash: CryptoHash, } -impl AsEvent for DeployCode { - fn metadata(&self) -> EventMetadata { +impl AsEvent for DeployCode { + fn metadata(&self) -> EventMetadata { EventMetadata { standard: "Upgradable".to_string(), version: "1.0.0".to_string(),