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
21 changes: 14 additions & 7 deletions src/components/member_manager.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,8 @@ pub mod MemberManagerComponent {
member.details.write(details);
member.member.write(new_member);
member.reg_time.write(reg_time);
member.total_received.write(Option::Some(0));
member.total_disbursements.write(Option::Some(0));
member.total_received.write(0);
member.total_disbursements.write(0);
self.member_count.write(id);

let factory_dispatcher = IFactoryDispatcher { contract_address: self.factory.read() };
Expand Down Expand Up @@ -371,12 +371,12 @@ pub mod MemberManagerComponent {
let mut member_node = self.members.entry(member_id);
member_node
.total_received
.write(Option::Some(member_node.total_received.read().unwrap() + 1));
.write(member_node.total_received.read() + 1);
member_node.no_of_payouts.write(member_node.no_of_payouts.read() + 1);
member_node.last_disbursement_timestamp.write(Option::Some(timestamp));
member_node.last_disbursement_timestamp.write(timestamp);
member_node
.total_disbursements
.write(Option::Some(member_node.total_disbursements.read().unwrap() + 1));
.write(member_node.total_disbursements.read() + 1);
}

/// Returns the address of the factory contract.
Expand All @@ -388,6 +388,13 @@ 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 {
let caller = get_caller_address();
self.admin_ca.entry(caller).read()
}
}

/// # InternalImpl
Expand Down Expand Up @@ -434,8 +441,8 @@ pub mod MemberManagerComponent {
new_admin_node.details.write(new_admin_details);
new_admin_node.member.write(new_admin);
new_admin_node.reg_time.write(reg_time);
new_admin_node.total_received.write(Option::Some(0));
new_admin_node.total_disbursements.write(Option::Some(0));
new_admin_node.total_received.write(0);
new_admin_node.total_disbursements.write(0);

self.admin_ca.entry(caller).write(true);
self.admin_ca.entry(owner).write(true);
Expand Down
121 changes: 117 additions & 4 deletions src/components/organization.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,20 @@
/// - Storing fundamental organization information (name, ID, owner, etc.).
/// - Managing a committee of privileged addresses.
/// - Handling organization-level configuration.
/// - Handling members' and interorganization business contracts
/// - Ownership transfers.
#[starknet::component]
pub mod OrganizationComponent {
use starknet::storage::{Map, StoragePointerReadAccess, StoragePointerWriteAccess};
use starknet::storage::{
Map, StoragePathEntry, StoragePointerReadAccess, StoragePointerWriteAccess,
};
use starknet::{ContractAddress, get_block_timestamp, get_caller_address};
// use crate::interfaces::icore::IConfig;
// use core::ec::stark_curve;
// use core::ecdsa;
use crate::interfaces::iorganization::IOrganization;
// use crate::structs::member_structs::MemberTrait;
use crate::structs::organization::{
OrganizationConfig, OrganizationConfigNode, OrganizationInfo, OrganizationType,
Contract, ContractParties, ContractStatus, ContractType, OrganizationConfig,
OrganizationConfigNode, OrganizationInfo, OrganizationType,
};
use super::super::member_manager::MemberManagerComponent;

Expand All @@ -29,6 +33,10 @@ pub mod OrganizationComponent {
pub config: OrganizationConfigNode, // refactor to OrganizationConfig
/// Struct containing the core information of the organization.
pub org_info: OrganizationInfo,
/// Maps an id to a contract
pub contracts: Map<u256, Contract>,
/// Contract counter
pub contract_counter: u64,
}

/// Events emitted by the `OrganizationComponent`.
Expand Down Expand Up @@ -91,6 +99,111 @@ pub mod OrganizationComponent {
fn get_organization_details(self: @ComponentState<TContractState>) -> OrganizationInfo {
self.org_info.read()
}

/// Creates an employee contract, to be given at hiring, or updated during employment
/// Show to employee at hiring
fn create_company_to_member_contract(
ref self: ComponentState<TContractState>,
contract_type: ContractType,
member_id: u256,
ipfs_hash: felt252,
expiry: Option<u64>,
) {
let member_component = get_dep_component!(@self, Member);
let caller = get_caller_address();
let is_admin = member_component.admin_ca.entry(caller).read();
assert(is_admin, 'Caller Not Permitted');

let contract = Contract {
id: self.contract_counter.read().into(),
hash: ipfs_hash,
version: 1,
signed_time: 0,
contract_parties: ContractParties::COMPANY_MEMBER(member_id),
status: ContractStatus::PROPOSED,
expiry_time: Option::None,
};

self.contracts.entry(self.contract_counter.read().into()).write(contract);
self.contract_counter.write(self.contract_counter.read() + 1);
}

/// Creates a contract between two companies using Littlefinger. Advanced features
/// Show to both companies
fn create_company_to_partner_contract(
ref self: ComponentState<TContractState>,
contract_type: ContractType,
partner_address: ContractAddress,
ipfs_hash: felt252,
expiry: Option<u64>,
) {
let member_component = get_dep_component!(@self, Member);
let caller = get_caller_address();
let is_admin = member_component.admin_ca.entry(caller).read();
assert(is_admin, 'Caller Not Permitted');

let contract = Contract {
id: self.contract_counter.read().into(),
hash: ipfs_hash,
version: 1,
signed_time: 0,
contract_parties: ContractParties::COMPANY_COMPANY(partner_address),
status: ContractStatus::PROPOSED,
expiry_time: Option::None,
};

self.contracts.entry(self.contract_counter.read().into()).write(contract);
self.contract_counter.write(self.contract_counter.read() + 1);
}

/// Used to accept a contract, by whoever is on the other side of the contract (recipeint)
/// Will implement Starknet message signing soon
fn sign_contract(
ref self: ComponentState<TContractState>, contract_id: u256, signature: Array<felt252>,
) {
// ecdsa::check_ecdsa_signature()
let mut contract = self.contracts.entry(contract_id).read();
contract.status = ContractStatus::ACTIVE;
contract.signed_time = get_block_timestamp();

self.contracts.entry(contract_id).write(contract);
}

/// Updates a contract ipfs hash and version
/// Show to employee at hiring
fn update_contract(
ref self: ComponentState<TContractState>,
contract_id: u256,
new_ipfs_hash: felt252,
expiry: Option<u64>,
) {
let mut contract = self.contracts.entry(contract_id).read();
contract.hash = new_ipfs_hash;

if expiry.is_some() {
contract.expiry_time = Option::Some(expiry.unwrap());
}
contract.version += 1;

self.contracts.entry(contract_id).write(contract);
}

/// Termminates a contract, can be used by employees or fellow companies
/// Mutual agreement between company and employee
fn terminate_contract(
ref self: ComponentState<TContractState>, contract_id: u256, signature: Array<felt252>,
) {
let mut contract = self.contracts.entry(contract_id).read();
contract.status = ContractStatus::TERMINATED;
}

/// Used to get a contract ipfs hash for access purpose
/// ### Returns
/// - Contract: all the important info of the contract suitable for storage onchain.
/// - The rest goes to IPFS
fn get_contract(self: @ComponentState<TContractState>, contract_id: u256) -> Contract {
self.contracts.entry(contract_id).read()
}
}

/// # InternalImpl
Expand Down
26 changes: 3 additions & 23 deletions src/contracts/core.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ mod Core {
use openzeppelin::upgrades::interface::IUpgradeable;
use starknet::storage::StoragePointerWriteAccess;
use starknet::{
ClassHash, ContractAddress, get_block_timestamp, get_caller_address, get_contract_address,
ClassHash, ContractAddress, get_block_timestamp, get_contract_address,
};
use crate::interfaces::imember_manager::IMemberManager;

Expand Down Expand Up @@ -158,9 +158,6 @@ mod Core {
deployer,
organization_type,
);
// MemberManagerComponent::InternalImpl::_initialize(
// ref self.member, first_admin_fname, first_admin_lname, first_admin_alias
// )
self
.member
._initialize(
Expand All @@ -173,9 +170,6 @@ mod Core {
);
self.vault_address.write(vault_address);
self.disbursement._init(owner);
// self.disbursement._add_authorized_caller(deployer);
// let this_contract = get_contract_address();
// self.disbursement._add_authorized_caller(this_contract);
self.ownable.initializer(owner);
}

Expand All @@ -197,8 +191,6 @@ mod Core {

// TODO: ADD ADMIN FROM HERE

// TODO: DO TRANSFER FROM HERE WHEN YOU WANT TO PAYOUT

/// # CoreImpl
///
/// Public-facing implementation of the `ICore` interface.
Expand All @@ -215,7 +207,6 @@ mod Core {
fn initialize_disbursement_schedule(
ref self: ContractState,
schedule_type: u8,
//schedule_id: felt252,
start: u64, //timestamp
end: u64,
interval: u64,
Expand All @@ -235,7 +226,6 @@ mod Core {
/// - If the payout is attempted before the required interval has passed since the last
/// execution.
fn schedule_payout(ref self: ContractState, token: ContractAddress) {
let caller = get_caller_address();
let members = self.member.get_members();
let no_of_members = members.len();

Expand All @@ -244,7 +234,6 @@ mod Core {

let vault_dispatcher = IVaultDispatcher { contract_address: vault_address };
let total_bonus = vault_dispatcher.get_bonus_allocation(token);
let total_funds = vault_dispatcher.get_token_balance(token);

let current_schedule = self.disbursement.get_current_schedule();
assert(current_schedule.status == ScheduleStatus::ACTIVE, 'Schedule not active');
Expand All @@ -260,8 +249,6 @@ mod Core {
);
}

// let mut failed_disbursements = array![];

// Everyone uses a base weight multiplier at the start, of 1
let mut total_weight: u16 = 0;
for i in 0..no_of_members {
Expand All @@ -271,19 +258,12 @@ 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);
let timestamp = get_block_timestamp();
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
2 changes: 1 addition & 1 deletion src/interfaces/imember_manager.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -228,5 +228,5 @@ pub trait IMemberManager<TContractState> {
// ROLE MANAGEMENT

// ALLOCATION WEIGHT MANAGEMENT (PROMOTION & DEMOTION)

fn is_admin(self: @TContractState, member_address: ContractAddress) -> bool;
}
36 changes: 35 additions & 1 deletion src/interfaces/iorganization.cairo
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use starknet::ContractAddress;
use crate::structs::organization::{OrganizationConfig, OrganizationInfo};
use crate::structs::organization::{Contract, ContractType, OrganizationConfig, OrganizationInfo};

// Some functions here might require multiple signing to execute.
/// # IOrganization
Expand Down Expand Up @@ -55,4 +55,38 @@ 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,
// parties: Array<ContractAddress>,
// ipfs_hash: felt252,
// expiry: Option<u64>,
// );

fn create_company_to_member_contract(
ref self: TContractState,
contract_type: ContractType,
member_id: u256,
ipfs_hash: felt252,
expiry: Option<u64>,
);

fn create_company_to_partner_contract(
ref self: TContractState,
contract_type: ContractType,
partner_address: ContractAddress,
ipfs_hash: felt252,
expiry: Option<u64>,
);

fn sign_contract(ref self: TContractState, contract_id: u256, signature: Array<felt252>);

fn update_contract(
ref self: TContractState, contract_id: u256, new_ipfs_hash: felt252, expiry: Option<u64>,
);

fn terminate_contract(ref self: TContractState, contract_id: u256, signature: Array<felt252>);

fn get_contract(self: @TContractState, contract_id: u256) -> Contract;
}
16 changes: 8 additions & 8 deletions src/structs/member_structs.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ pub struct MemberResponse {
// The base pay is agreed between the member and the company at the beginning of their work
// together i.e. during registration
pub base_pay: u256,
pub pending_allocations: Option<u256>,
pub total_received: Option<u256>,
pub pending_allocations: u256,
pub total_received: u256,
pub no_of_payouts: u32,
pub last_disbursement_timestamp: Option<u64>,
pub total_disbursements: Option<u64>,
pub last_disbursement_timestamp: u64,
pub total_disbursements: u64,
pub reg_time: u64,
}

Expand Down Expand Up @@ -63,11 +63,11 @@ pub struct MemberNode {
pub details: MemberDetails,
pub member: Member,
pub base_pay: u256,
pub pending_allocations: Option<u256>,
pub total_received: Option<u256>,
pub pending_allocations: u256,
pub total_received: u256,
pub no_of_payouts: u32,
pub last_disbursement_timestamp: Option<u64>,
pub total_disbursements: Option<u64>,
pub last_disbursement_timestamp: u64,
pub total_disbursements: u64,
pub reg_time: u64,
}

Expand Down
Loading
Loading