Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions contracts/analytics/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
use ink::prelude::string::String;
use ink::prelude::vec::Vec;

/// Standalone staking-dashboard helper with its own events, error type and
/// unit tests (wired into the crate per Issue #983; previously a dead file
/// that was never compiled or tested).
pub mod staking_dashboard;

#[ink::contract]
mod propchain_analytics {
use super::*;
Expand Down
22 changes: 11 additions & 11 deletions contracts/analytics/src/staking_dashboard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -339,18 +339,18 @@ mod tests {
use ink::env::test::default_accounts;

/// Build a fresh dashboard with zeroed-out state.
///
/// Must be called from within an `#[ink::test]` so the mapping's lazy
/// storage accesses have an initialized off-chain environment.
fn fresh() -> StakingDashboard {
ink::env::test::run_test::<ink::env::DefaultEnvironment, _>(|_| {
Ok(StakingDashboard {
staker_records: Mapping::default(),
total_staked: 0,
total_stakers: 0,
rewards_distributed: 0,
unclaimed_rewards: 0,
reward_per_token_stored: 0,
})
})
.unwrap()
StakingDashboard {
staker_records: Mapping::default(),
total_staked: 0,
total_stakers: 0,
rewards_distributed: 0,
unclaimed_rewards: 0,
reward_per_token_stored: 0,
}
}

fn accounts() -> ink::env::test::DefaultAccounts<ink::env::DefaultEnvironment> {
Expand Down
59 changes: 59 additions & 0 deletions contracts/gdpr/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,13 +203,28 @@ mod gdpr_consent {

// ── Consent Management ──────────────────────────────────────────────

/// Grants consent for a data subject and processing purpose.
///
/// Only the data subject themself may grant consent for their own
/// data; the contract admin may additionally record consent on behalf
/// of a subject (mirroring [`withdraw_consent`]'s authorization rule).
/// Any other caller is rejected with [`Error::NotAuthorized`] so
/// third parties cannot fabricate consent records in someone else's
/// name.
///
/// Returns the id of the newly created [`ConsentRecord`].
#[ink(message)]
pub fn grant_consent(
&mut self,
data_subject: AccountId,
purpose: ProcessingPurpose,
duration_ms: u64,
) -> Result<u64> {
let caller = self.env().caller();
if caller != data_subject && caller != self.admin {
return Err(Error::NotAuthorized);
}

if duration_ms == 0 {
return Err(Error::InvalidDuration);
}
Expand Down Expand Up @@ -564,6 +579,50 @@ mod gdpr_consent {
assert_eq!(result, Err(Error::InvalidDuration));
}

#[ink::test]
fn test_unauthorized_caller_cannot_grant_for_other() {
let mut contract = default_contract();
let subject = AccountId::from([0x02; 32]);
let attacker = AccountId::from([0x09; 32]);

ink::env::test::set_caller::<ink::env::DefaultEnvironment>(attacker);
let result =
contract.grant_consent(subject, ProcessingPurpose::KYC, 365 * 24 * 60 * 60 * 1000);
assert_eq!(result, Err(Error::NotAuthorized));

// No fabricated consent record exists and processing checks stay false.
assert!(contract.get_subject_consents(subject).is_empty());
assert!(!contract.check_consent(subject, ProcessingPurpose::KYC));
}

#[ink::test]
fn test_subject_can_grant_own_consent() {
let mut contract = default_contract();
let subject = AccountId::from([0x02; 32]);

ink::env::test::set_caller::<ink::env::DefaultEnvironment>(subject);
let id = contract
.grant_consent(subject, ProcessingPurpose::KYC, 365 * 24 * 60 * 60 * 1000)
.expect("self-grant");
let record = contract.get_consent(id).expect("should exist");
assert_eq!(record.data_subject, subject);
assert_eq!(record.status, ConsentStatus::Granted);
assert!(contract.check_consent(subject, ProcessingPurpose::KYC));
}

#[ink::test]
fn test_admin_can_grant_on_behalf_of_subject() {
let mut contract = default_contract(); // constructor caller is the admin
let subject = AccountId::from([0x02; 32]);

let id = contract
.grant_consent(subject, ProcessingPurpose::TaxReporting, 365 * 24 * 60 * 60 * 1000)
.expect("admin grant");
let record = contract.get_consent(id).expect("should exist");
assert_eq!(record.data_subject, subject);
assert!(contract.check_consent(subject, ProcessingPurpose::TaxReporting));
}

#[ink::test]
fn test_subject_requests_list() {
let mut contract = default_contract();
Expand Down
13 changes: 13 additions & 0 deletions contracts/governance/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,19 @@
clippy::manual_checked_ops
)]

// Required by the standalone `delegation` helper module in no_std builds.
extern crate alloc;

// Standalone governance helpers wired into the build per Issue #982 (they
// were previously dead files that were never compiled or tested). They are
// unit-tested by `cargo test -p propchain-governance`; exposing them on the
// on-chain message surface remains a separate feature decision.
pub mod delegation;
pub mod treasury;

#[cfg(test)]
mod snapshot_tests;

#[ink::contract]
mod governance {
use ink::prelude::vec::Vec;
Expand Down
2 changes: 0 additions & 2 deletions contracts/property-management/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1561,5 +1561,3 @@ mod property_management {
}
}
}

pub mod submodules;
11 changes: 0 additions & 11 deletions contracts/property-management/src/submodules.rs

This file was deleted.

Loading