diff --git a/.github/workflows/smoke-ci.yml b/.github/workflows/smoke-ci.yml index 36d234f05..e1dde811f 100644 --- a/.github/workflows/smoke-ci.yml +++ b/.github/workflows/smoke-ci.yml @@ -26,10 +26,15 @@ jobs: grep -Eq '^/contracts/lending/\s+@MettaChain/lending$' .github/CODEOWNERS grep -Eq '^/contracts/oracle/\s+@MettaChain/oracle$' .github/CODEOWNERS - - name: Install Stable Rust Toolchain + - name: Install Nightly Rust Toolchain (for fmt) + uses: dtolnay/rust-toolchain@nightly + with: + components: rustfmt + + - name: Install Stable Rust Toolchain (for clippy & test) uses: dtolnay/rust-toolchain@stable with: - components: rustfmt, clippy + components: clippy - name: Cache Cargo Build Artifacts uses: actions/cache@v4 @@ -44,8 +49,8 @@ jobs: restore-keys: | ${{ runner.os }}-cargo-smoke- - - name: Check Code Formatting Style (fmt) - run: cargo fmt --check + - name: Check Code Formatting Style (nightly fmt) + run: cargo +nightly fmt --check - name: Execute Static Analysis Compiler Lints (clippy) run: cargo clippy --all-targets --all-features -- -D warnings diff --git a/contracts/bridge/src/lib.rs b/contracts/bridge/src/lib.rs index 688383217..a8766efe1 100644 --- a/contracts/bridge/src/lib.rs +++ b/contracts/bridge/src/lib.rs @@ -18,9 +18,10 @@ use scale_info::prelude::vec::Vec; #[ink::contract] mod bridge { - use super::*; use propchain_traits::{non_reentrant, ReentrancyError, ReentrancyGuard}; + use super::*; + include!("errors.rs"); /// Maximum number of entries kept in [`PropertyBridge::pause_audit_log`]. diff --git a/contracts/compliance_registry/lib.rs b/contracts/compliance_registry/lib.rs index cbcc76c48..d46e46499 100644 --- a/contracts/compliance_registry/lib.rs +++ b/contracts/compliance_registry/lib.rs @@ -6,16 +6,16 @@ dead_code )] -use propchain_traits::ComplianceChecker; -use propchain_traits::*; +use propchain_traits::{ComplianceChecker, *}; #[ink::contract] mod compliance_registry { - use super::*; use ink::prelude::vec::Vec; use ink::storage::Mapping; use propchain_traits::ComplianceOperation; + use super::*; + /// Represents the verification status of a user #[derive(Debug, PartialEq, Eq, Clone, Copy, scale::Encode, scale::Decode)] #[cfg_attr( diff --git a/contracts/crowdfunding/src/lib.rs b/contracts/crowdfunding/src/lib.rs index add14ae93..ee2e9cc5e 100644 --- a/contracts/crowdfunding/src/lib.rs +++ b/contracts/crowdfunding/src/lib.rs @@ -10,8 +10,10 @@ use ink::storage::Mapping; #[ink::contract] mod propchain_crowdfunding { + use ink::prelude::string::String; + use ink::prelude::vec::Vec; + use super::*; - use ink::prelude::{string::String, vec::Vec}; #[derive(Debug, PartialEq, Eq, scale::Encode, scale::Decode)] #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] @@ -1428,11 +1430,12 @@ pub use crate::propchain_crowdfunding::{CrowdfundingError, RealEstateCrowdfundin #[cfg(test)] mod tests { - use super::*; #[allow(unused_imports)] use ink::env::{test, DefaultEnvironment}; use propchain_crowdfunding::{CampaignStatus, CrowdfundingError, RealEstateCrowdfunding}; + use super::*; + fn setup() -> RealEstateCrowdfunding { let accounts = test::default_accounts::(); test::set_caller::(accounts.alice); diff --git a/contracts/dex/src/lib.rs b/contracts/dex/src/lib.rs index 5215c4634..110efee12 100644 --- a/contracts/dex/src/lib.rs +++ b/contracts/dex/src/lib.rs @@ -6,15 +6,17 @@ clippy::needless_borrows_for_generic_args )] -use ink::prelude::{string::String, vec::Vec}; +use ink::prelude::string::String; +use ink::prelude::vec::Vec; use ink::storage::Mapping; use propchain_traits::*; #[ink::contract] mod dex { - use super::*; use propchain_traits::{non_reentrant, ReentrancyError, ReentrancyGuard}; + use super::*; + const BIPS_DENOMINATOR: u128 = 10_000; const REWARD_PRECISION: u128 = 1_000_000_000; diff --git a/contracts/factory/src/tests.rs b/contracts/factory/src/tests.rs index 58a474b92..5e2a8782d 100644 --- a/contracts/factory/src/tests.rs +++ b/contracts/factory/src/tests.rs @@ -1,7 +1,8 @@ -use crate::contract_factory::*; use ink::env::test; use ink::primitives::Hash; +use crate::contract_factory::*; + #[ink::test] fn test_factory_initialization() { let factory = ContractFactory::new(); diff --git a/contracts/fractional/src/lib.rs b/contracts/fractional/src/lib.rs index c5385e66b..96e0202d2 100644 --- a/contracts/fractional/src/lib.rs +++ b/contracts/fractional/src/lib.rs @@ -10,8 +10,7 @@ mod fractional { use ink::prelude::vec::Vec; use ink::storage::Mapping; - use propchain_traits; - use propchain_traits::{non_reentrant, ReentrancyError, ReentrancyGuard}; + use propchain_traits::{self, non_reentrant, ReentrancyError, ReentrancyGuard}; #[derive( Debug, @@ -1196,9 +1195,10 @@ mod fractional { #[cfg(test)] mod tests { - use super::*; use ink::env::test; + use super::*; + fn alice() -> AccountId { test::default_accounts::().alice } @@ -1894,9 +1894,10 @@ mod fractional { #[cfg(test)] mod fractional_admin_rotation_tests { - use super::*; use ink::env::{test, DefaultEnvironment}; + use super::*; + fn setup() -> Fractional { let accounts = test::default_accounts::(); test::set_caller::(accounts.alice); diff --git a/contracts/hello-world/src/test.rs b/contracts/hello-world/src/test.rs index ec9cea2a6..3453e8296 100644 --- a/contracts/hello-world/src/test.rs +++ b/contracts/hello-world/src/test.rs @@ -1,9 +1,10 @@ #![cfg(test)] #![allow(dead_code, unused_imports, deprecated)] -use super::*; use soroban_sdk::Env; +use super::*; + #[test] fn test_loan_lifecycle() { let env = Env::default(); diff --git a/contracts/insurance/src/lib.rs b/contracts/insurance/src/lib.rs index fad01f2af..ade987a7a 100644 --- a/contracts/insurance/src/lib.rs +++ b/contracts/insurance/src/lib.rs @@ -25,10 +25,12 @@ mod fraud_detection; /// Decentralized Property Insurance Platform #[ink::contract] mod propchain_insurance { - use super::*; - use ink::prelude::{string::String, vec::Vec}; + use ink::prelude::string::String; + use ink::prelude::vec::Vec; use propchain_traits::{non_reentrant, ReentrancyError, ReentrancyGuard}; + use super::*; + // Error types extracted to errors.rs (Issue #101) include!("errors.rs"); @@ -84,10 +86,9 @@ mod propchain_insurance { } // Risk Assessment Model (Task #254) - use crate::risk_assessment::risk_model; - // Fraud Detection System (Task #258) use crate::fraud_detection::fraud_detection; + use crate::risk_assessment::risk_model; // Premium calculation engine include!("premium_engine.rs"); diff --git a/contracts/insurance/src/tests.rs b/contracts/insurance/src/tests.rs index 183cd8ba1..78992c35f 100644 --- a/contracts/insurance/src/tests.rs +++ b/contracts/insurance/src/tests.rs @@ -18,10 +18,11 @@ // ============================================================================ #[cfg(test)] mod reinsurance_stats_derives { + use ink::env::{test, DefaultEnvironment}; + use crate::propchain_insurance::{ CoverageType, PropertyInsurance, ReinsuranceStats, ReinsuranceTreatyType, }; - use ink::env::{test, DefaultEnvironment}; fn setup() -> PropertyInsurance { let accounts = test::default_accounts::(); @@ -1701,9 +1702,10 @@ mod insurance_tests { #[cfg(test)] mod circuit_breaker_tests { - use crate::propchain_insurance::{CoverageType, InsuranceError, PropertyInsurance}; use ink::env::{test, DefaultEnvironment}; + use crate::propchain_insurance::{CoverageType, InsuranceError, PropertyInsurance}; + fn setup_with_pool() -> (PropertyInsurance, u64) { let accounts = test::default_accounts::(); test::set_caller::(accounts.alice); @@ -1797,9 +1799,10 @@ mod circuit_breaker_tests { #[cfg(test)] mod insurance_admin_rotation_tests { - use crate::propchain_insurance::{InsuranceError, PropertyInsurance}; use ink::env::{test, DefaultEnvironment}; + use crate::propchain_insurance::{InsuranceError, PropertyInsurance}; + fn setup() -> PropertyInsurance { let accounts = test::default_accounts::(); test::set_caller::(accounts.alice); diff --git a/contracts/lending/src/lib.rs b/contracts/lending/src/lib.rs index 3691bc3a6..f1c76103a 100644 --- a/contracts/lending/src/lib.rs +++ b/contracts/lending/src/lib.rs @@ -12,8 +12,10 @@ mod status_packing; #[ink::contract] mod propchain_lending { + use ink::prelude::string::String; + use ink::prelude::vec::Vec; + use super::*; - use ink::prelude::{string::String, vec::Vec}; #[derive(Debug, PartialEq, Eq, scale::Encode, scale::Decode)] #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] @@ -2149,10 +2151,11 @@ pub use crate::propchain_lending::{ /// when a bug fix requires a regression guard. #[cfg(test)] mod tests { - use super::*; use ink::env::{test, DefaultEnvironment}; use propchain_lending::PropertyLending; + use super::*; + fn setup() -> PropertyLending { let accounts = test::default_accounts::(); test::set_caller::(accounts.alice); @@ -2603,9 +2606,10 @@ mod tests { /// caller permutations) does not add noise to general lending tests. #[cfg(test)] mod lending_admin_rotation_tests { - use super::propchain_lending::{LendingError, PropertyLending}; use ink::env::{test, DefaultEnvironment}; + use super::propchain_lending::{LendingError, PropertyLending}; + fn setup() -> PropertyLending { let accounts = test::default_accounts::(); test::set_caller::(accounts.alice); @@ -2708,12 +2712,13 @@ mod lending_admin_rotation_tests { /// these tests is entirely in the type-checker. #[cfg(test)] mod storage_derivation_tests { + use scale::{Decode, Encode}; + use super::propchain_lending::{ CollateralKind, CollateralRecord, CreditProfile, LendingPool, LoanApplication, LoanListing, LoanOffer, LoanRestructuring, LoanServicer, LoanStatus, MarginPosition, PaymentSchedule, PaymentScheduleStatus, PropertyLending, Proposal, YieldPosition, }; - use scale::{Decode, Encode}; fn assert_storage_type< T: Encode + Decode + scale_info::TypeInfo + ink::storage::traits::StorageLayout, diff --git a/contracts/lending/src/test.rs b/contracts/lending/src/test.rs index 1c5723b8c..3a03e7b6f 100644 --- a/contracts/lending/src/test.rs +++ b/contracts/lending/src/test.rs @@ -1,12 +1,11 @@ #![allow(clippy::duplicated_attributes)] #![cfg(test)] -use super::*; -use crate::propchain_lending::CollateralKind; -use crate::propchain_lending::PaymentScheduleStatus; -use crate::propchain_lending::Schedule; use ink::env::{test, DefaultEnvironment}; +use super::*; +use crate::propchain_lending::{CollateralKind, PaymentScheduleStatus, Schedule}; + #[ink::test] fn test_loan_interest_accrual_is_jit_only_on_loan_modification() { let accounts = test::default_accounts::(); diff --git a/contracts/lib/src/lib.rs b/contracts/lib/src/lib.rs index 82b7488df..22a8cbe3d 100644 --- a/contracts/lib/src/lib.rs +++ b/contracts/lib/src/lib.rs @@ -11,16 +11,13 @@ use ink::prelude::string::String; use ink::prelude::vec::Vec; use ink::storage::Mapping; - +// Import identity module +use propchain_identity::propchain_identity::IdentityRegistryRef; // Re-export traits pub use propchain_traits::*; - // Re-export reentrancy protection pub use reentrancy_guard::{ReentrancyError, ReentrancyGuard}; -// Import identity module -use propchain_identity::propchain_identity::IdentityRegistryRef; - // Export error handling utilities #[cfg(feature = "std")] pub mod error_handling; @@ -4641,10 +4638,11 @@ pub mod propchain_contracts { #[cfg(test)] mod tests_pause { - use super::propchain_contracts::{Error, ExternalDependency, PropertyRegistry}; use ink::primitives::AccountId; use propchain_traits::PropertyMetadata; + use super::propchain_contracts::{Error, ExternalDependency, PropertyRegistry}; + #[ink::test] fn test_pause_resume_flow() { let mut contract = PropertyRegistry::new(); diff --git a/contracts/mock-oracle/src/lib.rs b/contracts/mock-oracle/src/lib.rs index b4306d844..77784f471 100644 --- a/contracts/mock-oracle/src/lib.rs +++ b/contracts/mock-oracle/src/lib.rs @@ -518,9 +518,9 @@ mod mock_oracle_contract { #[cfg(test)] mod tests { + use ink::env::{test, DefaultEnvironment}; + use super::*; - use ink::env::test; - use ink::env::DefaultEnvironment; fn setup() -> MockOracle { let accounts = test::default_accounts::(); diff --git a/contracts/multicall/src/lib.rs b/contracts/multicall/src/lib.rs index 85a8ba03f..a3bcc994e 100644 --- a/contracts/multicall/src/lib.rs +++ b/contracts/multicall/src/lib.rs @@ -274,9 +274,9 @@ mod propchain_multicall { #[cfg(test)] mod tests { + use ink::env::{test, DefaultEnvironment}; + use super::*; - use ink::env::test; - use ink::env::DefaultEnvironment; fn setup() -> MulticallContract { let accounts = test::default_accounts::(); diff --git a/contracts/oracle/src/lib.rs b/contracts/oracle/src/lib.rs index f4d36f783..0926e9c02 100644 --- a/contracts/oracle/src/lib.rs +++ b/contracts/oracle/src/lib.rs @@ -26,10 +26,8 @@ mod aggregation; mod propchain_oracle { use super::*; include!("types.rs"); - use ink::prelude::{ - string::{String, ToString}, - vec::Vec, - }; + use ink::prelude::string::{String, ToString}; + use ink::prelude::vec::Vec; /// Aggregation mode used when combining prices from multiple oracle sources. #[derive( diff --git a/contracts/property-management/src/lib.rs b/contracts/property-management/src/lib.rs index 58c2a0772..5ecf40153 100644 --- a/contracts/property-management/src/lib.rs +++ b/contracts/property-management/src/lib.rs @@ -1338,9 +1338,10 @@ mod property_management { #[cfg(test)] mod tests { - use super::*; use ink::env::{test, DefaultEnvironment}; + use super::*; + fn setup() -> PropertyManagement { PropertyManagement::new() } diff --git a/contracts/traits/src/admin_multisig.rs b/contracts/traits/src/admin_multisig.rs index 2db2643dc..f0794681e 100644 --- a/contracts/traits/src/admin_multisig.rs +++ b/contracts/traits/src/admin_multisig.rs @@ -1,6 +1,7 @@ -use crate::AccountId; use ink::prelude::vec::Vec; +use crate::AccountId; + pub trait MultiSigAdminRotationTrait { fn confirm_key_rotation(&mut self, approvals: Vec) -> Result<(), &'static str>; } diff --git a/contracts/traits/src/bridge.rs b/contracts/traits/src/bridge.rs index dc5161f42..478d70609 100644 --- a/contracts/traits/src/bridge.rs +++ b/contracts/traits/src/bridge.rs @@ -3,11 +3,12 @@ //! This module contains all bridge-related types, status enums, configuration //! structures, and trait definitions for cross-chain property token bridging. -use crate::property::{ChainId, PropertyMetadata, TokenId}; use ink::prelude::string::String; use ink::prelude::vec::Vec; use ink::primitives::AccountId; +use crate::property::{ChainId, PropertyMetadata, TokenId}; + // ========================================================================= // Data Types // ========================================================================= diff --git a/contracts/traits/src/dex.rs b/contracts/traits/src/dex.rs index f135a443e..5914c314c 100644 --- a/contracts/traits/src/dex.rs +++ b/contracts/traits/src/dex.rs @@ -3,12 +3,13 @@ //! This module contains all types related to the decentralized exchange, //! order book, liquidity pools, governance, and cross-chain trading. -use crate::bridge::BridgeFeeQuote; -use crate::property::{ChainId, TokenId}; use ink::prelude::string::String; use ink::prelude::vec::Vec; use ink::primitives::AccountId; +use crate::bridge::BridgeFeeQuote; +use crate::property::{ChainId, TokenId}; + // ========================================================================= // Order and Trading Types // ========================================================================= diff --git a/contracts/traits/src/errors.rs b/contracts/traits/src/errors.rs index 602924937..45a7f4129 100644 --- a/contracts/traits/src/errors.rs +++ b/contracts/traits/src/errors.rs @@ -10,8 +10,8 @@ //! - [`ContractError::error_i18n_key()`]: default method returning a localization key use core::fmt; -use scale::{Decode, Encode}; +use scale::{Decode, Encode}; #[cfg(feature = "std")] use scale_info::TypeInfo; diff --git a/contracts/traits/src/event_bus.rs b/contracts/traits/src/event_bus.rs index e5b2b16c3..7950a9ea5 100644 --- a/contracts/traits/src/event_bus.rs +++ b/contracts/traits/src/event_bus.rs @@ -1,9 +1,9 @@ #![allow(clippy::module_name_repetitions)] use core::fmt; + use ink::prelude::vec::Vec; use scale::{Decode, Encode}; - #[cfg(feature = "std")] use scale_info::TypeInfo; diff --git a/contracts/traits/src/i18n.rs b/contracts/traits/src/i18n.rs index d6e3f1535..3521377e4 100644 --- a/contracts/traits/src/i18n.rs +++ b/contracts/traits/src/i18n.rs @@ -15,7 +15,6 @@ //! inside each key's match block, following the English arm as the template. use scale::{Decode, Encode}; - #[cfg(feature = "std")] use scale_info::TypeInfo; diff --git a/contracts/traits/src/lib.rs b/contracts/traits/src/lib.rs index 84614a42e..252bf3184 100644 --- a/contracts/traits/src/lib.rs +++ b/contracts/traits/src/lib.rs @@ -12,12 +12,11 @@ pub mod randomness; pub mod reentrancy_guard; pub mod types; -pub use types::*; - pub use access_control::*; pub use crypto::*; pub use di::*; pub use reentrancy_guard::*; +pub use types::*; pub mod i18n; pub mod monitoring; pub mod property_token_metadata; @@ -41,23 +40,20 @@ pub mod property; // ========================================================================= // Original re-exports -pub use errors::*; -pub use i18n::*; -pub use monitoring::*; - // Re-export all new module contents at the crate root so that // existing `use propchain_traits::*` continues to resolve every type. pub use bridge::*; -pub use dex::*; -pub use oracle::*; -pub use property::*; - // Re-export compliance and fee module contents (types are defined in those modules) pub use compliance::*; +pub use dex::*; +pub use errors::*; pub use event_bus::*; pub use fee::*; +pub use i18n::*; +pub use monitoring::*; pub use multicall::*; - +pub use oracle::*; +pub use property::*; #[cfg(not(feature = "std"))] use scale_info::prelude::vec::Vec; diff --git a/contracts/traits/src/monitoring.rs b/contracts/traits/src/monitoring.rs index 430bdd705..7d6c0d4a9 100644 --- a/contracts/traits/src/monitoring.rs +++ b/contracts/traits/src/monitoring.rs @@ -1,7 +1,7 @@ use core::fmt; + use ink::prelude::vec::Vec; use scale::{Decode, Encode}; - #[cfg(feature = "std")] use scale_info::TypeInfo; diff --git a/contracts/traits/src/multicall.rs b/contracts/traits/src/multicall.rs index f267f6941..70592e303 100644 --- a/contracts/traits/src/multicall.rs +++ b/contracts/traits/src/multicall.rs @@ -157,9 +157,10 @@ pub fn aggregate_verifications( #[cfg(test)] mod tests { - use super::*; use ink::primitives::AccountId; + use super::*; + #[test] fn selectors_are_distinct_across_kinds() { let kinds = [ diff --git a/contracts/traits/src/oracle.rs b/contracts/traits/src/oracle.rs index 4cf8579aa..8d07755d3 100644 --- a/contracts/traits/src/oracle.rs +++ b/contracts/traits/src/oracle.rs @@ -4,12 +4,13 @@ //! definitions used across the PropChain ecosystem for property valuations, //! price feeds, and market analysis. -use crate::errors::{ContractError, ErrorCategory}; -use crate::property::PropertyType; use ink::prelude::string::String; use ink::prelude::vec::Vec; use ink::primitives::AccountId; +use crate::errors::{ContractError, ErrorCategory}; +use crate::property::PropertyType; + // ========================================================================= // Error Types // ========================================================================= diff --git a/contracts/traits/src/property.rs b/contracts/traits/src/property.rs index 7f3e589ab..6cd52ee01 100644 --- a/contracts/traits/src/property.rs +++ b/contracts/traits/src/property.rs @@ -3,11 +3,12 @@ //! This module contains the core property-related types, metadata structures, //! and trait definitions for property registration, escrow, and management. -use crate::compliance::Jurisdiction; use ink::prelude::string::String; use ink::prelude::vec::Vec; use ink::primitives::AccountId; +use crate::compliance::Jurisdiction; + // ========================================================================= // Data Types // ========================================================================= diff --git a/contracts/version-registry/src/lib.rs b/contracts/version-registry/src/lib.rs index f4d389b72..f74231aed 100644 --- a/contracts/version-registry/src/lib.rs +++ b/contracts/version-registry/src/lib.rs @@ -270,9 +270,10 @@ mod version_registry { #[cfg(test)] mod tests { - use super::*; use ink::env::test; + use super::*; + fn default_registry() -> VersionRegistry { VersionRegistry::new() } diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 000000000..09871c659 --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,8 @@ +# Pins the nightly toolchain so that `format_macro_matchers` and other +# nightly-only rustfmt options work consistently across all contributors +# and in CI. The `rustfmt` component is listed explicitly so that +# `cargo fmt` resolves to the nightly formatter regardless of any system +# default. +[toolchain] +channel = "nightly" +components = ["rustfmt", "clippy"] diff --git a/security-audit/src/main.rs b/security-audit/src/main.rs index c6795391e..222967547 100644 --- a/security-audit/src/main.rs +++ b/security-audit/src/main.rs @@ -1,9 +1,10 @@ +use std::fs; +use std::process::Command; + use anyhow::{Context, Result}; use clap::{Parser, Subcommand}; use colored::*; use serde::{Deserialize, Serialize}; -use std::fs; -use std::process::Command; use walkdir::WalkDir; #[derive(Parser)]