Skip to content
Closed
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
1 change: 0 additions & 1 deletion src/components/member_manager.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,6 @@ pub mod MemberManagerComponent {
fn get_core_org_address(self: @ComponentState<TContractState>) -> ContractAddress {
self.core_org.read()
}

fn is_admin(
self: @ComponentState<TContractState>, member_address: ContractAddress,
) -> bool {
Expand Down
8 changes: 4 additions & 4 deletions src/components/organization.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@
/// - Ownership transfers.
#[starknet::component]
pub mod OrganizationComponent {
use starknet::storage::{
Map, StoragePathEntry, StoragePointerReadAccess, StoragePointerWriteAccess,
};
use starknet::storage::{Map, StoragePathEntry,StoragePointerReadAccess, StoragePointerWriteAccess};
use starknet::{ContractAddress, get_block_timestamp, get_caller_address};
// use core::ec::stark_curve;
// use core::ecdsa;
Expand All @@ -21,7 +19,6 @@ pub mod OrganizationComponent {
};
use super::super::member_manager::MemberManagerComponent;


/// Defines the storage layout for the `OrganizationComponent`.
#[storage]
pub struct Storage {
Expand Down Expand Up @@ -79,6 +76,8 @@ pub mod OrganizationComponent {
add: Array<ContractAddress>,
subtract: Array<ContractAddress>,
) { // any one subtracted, power would be taken down to zero.


}

/// Updates the organization's configuration.
Expand Down Expand Up @@ -205,6 +204,7 @@ pub mod OrganizationComponent {
self.contracts.entry(contract_id).read()
}
}


/// # InternalImpl
///
Expand Down
143 changes: 143 additions & 0 deletions src/components/permission_manager.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
/// ## A Starknet component for managing granular permissions.
///
/// This component assigns specific permissions to accounts using a bitmask.
#[starknet::component]
pub mod PermissionManagerComponent {
use starknet::storage::{Map, StoragePointerReadAccess, StoragePointerWriteAccess};
use starknet::{ContractAddress, get_caller_address};
use core::array::{ArrayTrait, array, SpanTrait};
use core::option::OptionTrait;
use core::integer::u256;

/// Permissions in the organization, represented as a bitmask.
#[derive(Copy, Drop, Serde, PartialEq)]
pub enum Permission {
ADD_MEMBER = 1,
REMOVE_MEMBER = 2,
SEND_INVITES = 4,
SET_SALARIES = 8,
SET_DISBURSEMENT = 16,
ADD_VAULT_TOKENS = 32,
VAULT_FUNCTIONS = 64,
GRANT_ADMIN = 128,
REVOKE_ADMIN = 256,
}

/// Defines the storage layout for the `PermissionManagerComponent`.
#[storage]
pub struct Storage {
/// Maps an address to its bitmask of permissions.
pub permissions: Map<ContractAddress, u256>,
}

/// Events emitted by the `PermissionManagerComponent`.
#[event]
#[derive(Drop, starknet::Event)]
pub enum Event {
PermissionGranted: PermissionGranted,
PermissionRevoked: PermissionRevoked,
AllPermissionsGranted: AllPermissionsGranted,
AllPermissionsRevoked: AllPermissionsRevoked,
}

#[derive(Drop, starknet::Event)]
pub struct PermissionGranted {
#[key]
pub account: ContractAddress,
pub permission: Permission,
}

#[derive(Drop, starknet::Event)]
pub struct PermissionRevoked {
#[key]
pub account: ContractAddress,
pub permission: Permission,
}

#[derive(Drop, starknet::Event)]
pub struct AllPermissionsGranted {
#[key]
pub account: ContractAddress,
}

#[derive(Drop, starknet::Event)]
pub struct AllPermissionsRevoked {
#[key]
pub account: ContractAddress,
}

/// # PermissionManagerComponent
///
/// Public-facing API for permission management.
#[embeddable_as(PermissionManager)]
pub impl Permission<
TContractState, +HasComponent<TContractState>, +Drop<TContractState>,
> of crate::interfaces::ipermission::IPermission<ComponentState<TContractState>> {
/// Grants a specific permission to an account.
fn grant_permission(ref self: ComponentState<TContractState>, account: ContractAddress, permission: Permission) {
let caller = get_caller_address();
let has_permission = self.internal._has_permission(caller, Permission::GRANT_ADMIN);
assert(has_permission, 'Perm: caller not admin');

let mut current_permissions = self.permissions.read(account);
current_permissions = current_permissions | (permission.into());
self.permissions.write(account, current_permissions);
self.emit(Event::PermissionGranted(PermissionGranted { account, permission }));
}

/// Revokes a specific permission from an account.
fn revoke_permission(ref self: ComponentState<TContractState>, account: ContractAddress, permission: Permission) {
let caller = get_caller_address();
let has_permission = self.internal._has_permission(caller, Permission::REVOKE_ADMIN);
assert(has_permission, 'Perm: caller not admin');

let mut current_permissions = self.permissions.read(account);
current_permissions = current_permissions & (!(permission.into()));
self.permissions.write(account, current_permissions);
self.emit(Event::PermissionRevoked(PermissionRevoked { account, permission }));
}

/// Grants all permissions to an account.
fn grant_all_permissions(ref self: ComponentState<TContractState>, account: ContractAddress) {
let caller = get_caller_address();
let has_permission = self.internal._has_permission(caller, Permission::GRANT_ADMIN);
assert(has_permission, 'Perm: caller not admin');

// Set all bits to 1 (full permissions)
let all_perms = 511; // Sum of all enum values
self.permissions.write(account, all_perms);
self.emit(Event::AllPermissionsGranted(AllPermissionsGranted { account }));
}

/// Revokes all permissions from an account.
fn revoke_all_permissions(ref self: ComponentState<TContractState>, account: ContractAddress) {
let caller = get_caller_address();
let has_permission = self.internal._has_permission(caller, Permission::REVOKE_ADMIN);
assert(has_permission, 'Perm: caller not admin');

self.permissions.write(account, 0);
self.emit(Event::AllPermissionsRevoked(AllPermissionsRevoked { account }));
}

/// Checks if an account has a specific permission.
fn has_permission(self: @ComponentState<TContractState>, account: ContractAddress, permission: Permission) -> bool {
self.internal._has_permission(account, permission)
}
}

/// # InternalImpl
#[generate_trait]
pub impl InternalImpl<TContractState, +HasComponent<TContractState>, > of PermissionInternalTrait<TContractState> {
/// Initializes the permission manager with an owner who has all permissions.
fn _init(ref self: ComponentState<TContractState>, owner: ContractAddress) {
let all_perms = 511; // Sum of all enum values
self.permissions.write(owner, all_perms);
}

/// Internal function to check if an account has a specific permission.
fn _has_permission(self: @ComponentState<TContractState>, account: ContractAddress, permission: Permission) -> bool {
let account_perms = self.permissions.read(account);
(account_perms & (permission.into())) != 0
}
}
}
9 changes: 8 additions & 1 deletion src/contracts/core.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -258,12 +258,19 @@ mod Core {
}
for i in 0..no_of_members {
let current_member_response = *members.at(i);
// let pseudo_current_member = Member {
// id: current_member_response.id,
// address: current_member_response.address,
// status: current_member_response.status,
// role: current_member_response.role,
// // base_pay: current_member_response.base_pay,
// };
let timestamp = get_block_timestamp();
let amount = self
.disbursement
.compute_renumeration(current_member_response, total_bonus, total_weight);
vault_dispatcher.pay_member(token, current_member_response.address, amount);
self.member.record_member_payment(current_member_response.id, amount, timestamp)
self.member.record_member_payment(current_member_response.id, amount, timestamp);
}

self.disbursement.update_current_schedule_last_execution(now);
Expand Down
1 change: 0 additions & 1 deletion src/interfaces/iorganization.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ pub trait IOrganization<TContractState> {
///
/// An `OrganizationInfo` struct containing the organization's details.
fn get_organization_details(self: @TContractState) -> OrganizationInfo;

// fn create_contract(
// ref self: TContractState,
// contract_type: ContractType,
Expand Down
2 changes: 1 addition & 1 deletion src/structs/organization.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ pub struct OrganizationConfig {
pub struct OrganizationConfigNode {
pub additional_data: Vec<felt252>,
}

#[allow(starknet::store_no_default_variant)]
#[derive(Copy, Drop, Serde, starknet::Store)]
pub enum ContractType {
Expand Down Expand Up @@ -98,3 +97,4 @@ impl ContractImpl of ContractTrait {
default_contract
}
}