Skip to content

Commit b3658d9

Browse files
authored
Merge pull request #1 from crowdpass-live/feat/add-or-remove-organizer
Feat/add or remove organizer
2 parents 115681a + 2fa3d7c commit b3658d9

File tree

5 files changed

+160
-108
lines changed

5 files changed

+160
-108
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
target
22
.snfoundry_cache/
33

4+
# profile and trace files
5+
profile
6+
snfoundry_trace
7+
48
.DS_Store

src/errors.cairo

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ pub mod Errors {
66
pub const ZERO_AMOUNT: felt252 = 'Amount cannot be zero';
77
pub const ZERO_ADDRESS_CALLER: felt252 = 'Caller cannot be zero address';
88
pub const ZERO_ADDRESS_OWNER: felt252 = 'Owner cannot be zero address';
9-
pub const NOT_EVENT_ORGANIZER: felt252 = 'Caller not organizer';
9+
pub const NOT_EVENT_ORGANIZER: felt252 = 'Caller not main organizer';
1010
pub const EVENT_NOT_CREATED: felt252 = 'Event not yet created';
1111
pub const EVENT_ENDED: felt252 = 'Event has ended';
1212
pub const EVENT_CANCELED: felt252 = 'Event is canceled';

src/event_factory/event_factory.cairo

Lines changed: 121 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,6 @@ pub mod EventFactory {
107107
upgradeable: UpgradeableComponent::Storage,
108108
event_count: u256,
109109
events: Map<u256, EventData>,
110-
event_array: Array<EventData>,
111110
event_ticket_balance: Map<u256, u256>,
112111
strk_token_address: felt252,
113112
ticket_721_class_hash: felt252,
@@ -152,72 +151,21 @@ pub mod EventFactory {
152151
end_date: u64,
153152
total_tickets: u256,
154153
ticket_price: u256,
155-
) -> bool {
156-
let caller = get_caller_address();
157-
let event_count = self.event_count.read() + 1;
158-
let address_this = get_contract_address();
159-
160-
// assert not zero ContractAddress
161-
assert(caller.is_non_zero(), Errors::ZERO_ADDRESS_CALLER);
162-
163-
// create event role
164-
let event_hash = PedersenTrait::new(0)
165-
.update('CROWD_PASS_EVENT')
166-
.update(event_count.try_into().unwrap())
167-
.finalize();
168-
// grant role to caller
169-
self.accesscontrol._grant_role(event_hash, caller);
170-
171-
// let event_ticket_addr = self.deploy_ticket(address_this, address_this, ''.into());
172-
173-
// deploy ticket721 contract
174-
let event_ticket = deploy_syscall(
175-
self.ticket_721_class_hash.read().try_into().unwrap(),
176-
event_hash,
177-
array![address_this.into(), address_this.into()].span(),
178-
true,
179-
);
180-
181-
let (event_ticket_addr, _) = event_ticket.unwrap_syscall();
182-
183-
// initialize ticket721 contract
184-
ITicket721Dispatcher { contract_address: event_ticket_addr }
185-
.initialize(name, symbol, uri,);
186-
187-
// new event struct instance
188-
let event_instance = EventData {
189-
id: event_count,
190-
organizer: caller,
191-
ticket_addr: event_ticket_addr,
192-
description: description,
193-
location: location,
194-
created_at: get_block_timestamp(),
195-
updated_at: 0,
196-
start_date: start_date,
197-
end_date: end_date,
198-
total_tickets: total_tickets,
199-
ticket_price: ticket_price,
200-
is_canceled: false,
201-
};
202-
203-
// Map event_id to new_event
204-
self.events.entry(event_count).write(event_instance);
205-
206-
// Append event to event_array
207-
// self.event_array.append(event_instance);
208-
209-
// Update event count
210-
self.event_count.write(event_count);
211-
212-
// emit event for event creation
213-
self
214-
.emit(
215-
EventCreated {
216-
id: event_count, organizer: caller, ticket_address: event_ticket_addr
217-
}
154+
) -> EventData {
155+
let event = self
156+
._create_event(
157+
name,
158+
symbol,
159+
uri,
160+
description,
161+
location,
162+
start_date,
163+
end_date,
164+
total_tickets,
165+
ticket_price
218166
);
219167

220-
true
168+
event
221169
}
222170

223171
fn update_event(
@@ -235,10 +183,7 @@ pub mod EventFactory {
235183
) -> bool {
236184
let caller = get_caller_address();
237185

238-
let event_hash = PedersenTrait::new(0)
239-
.update('CROWD_PASS_EVENT')
240-
.update(event_id.try_into().unwrap())
241-
.finalize();
186+
let event_hash = self._gen_event_hash(event_id);
242187
// assert caller has role
243188
self.accesscontrol.assert_only_role(event_hash);
244189

@@ -269,17 +214,14 @@ pub mod EventFactory {
269214
let organizer = self.events.entry(event_id).read().organizer;
270215
let mut event_instance = self.events.entry(event_id).read();
271216

272-
let event_hash = PedersenTrait::new(0)
273-
.update('CROWD_PASS_EVENT')
274-
.update(event_id.try_into().unwrap())
275-
.finalize();
276-
// assert caller has role
277-
self.accesscontrol.assert_only_role(event_hash);
217+
let event_hash = self._gen_event_hash(event_id);
278218

279219
assert(event_id <= event_count, Errors::EVENT_NOT_CREATED);
280220
// assert not zeroAddr caller
281221
assert(caller.is_non_zero(), Errors::ZERO_ADDRESS_CALLER);
282-
// assert caller is event organizer
222+
// assert caller has role
223+
self.accesscontrol.assert_only_role(event_hash);
224+
// assert caller is the main event organizer
283225
assert(caller == organizer, Errors::NOT_EVENT_ORGANIZER);
284226
// assert event has not ended
285227
assert(event_instance.end_date > get_block_timestamp(), Errors::EVENT_ENDED);
@@ -293,6 +235,17 @@ pub mod EventFactory {
293235
true
294236
}
295237

238+
fn add_organizer(ref self: ContractState, event_id: u256, organizer: ContractAddress) {
239+
let event_hash = self._gen_event_hash(event_id);
240+
self.accesscontrol.assert_only_role(event_hash);
241+
self._add_organizer(event_hash, organizer);
242+
}
243+
fn remove_organizer(ref self: ContractState, event_id: u256, organizer: ContractAddress) {
244+
let event_hash = self._gen_event_hash(event_id);
245+
self.accesscontrol.assert_only_role(event_hash);
246+
self._remove_organizer(event_hash, organizer);
247+
}
248+
296249
fn purchase_ticket(ref self: ContractState, event_id: u256) -> bool {
297250
let caller: ContractAddress = get_caller_address();
298251
let event_count: u256 = self.event_count.read();
@@ -413,6 +366,98 @@ pub mod EventFactory {
413366
//////////////////////////////////////////////////////////////////////////*//
414367
impl AccessControlInternalImpl = AccessControlComponent::InternalImpl<ContractState>;
415368
impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl<ContractState>;
369+
370+
#[generate_trait]
371+
impl InternalImpl of InternalTrait {
372+
fn _gen_event_hash(self: @ContractState, event_id: u256) -> felt252 {
373+
PedersenTrait::new(0)
374+
.update('CROWD_PASS_EVENT')
375+
.update(event_id.try_into().unwrap())
376+
.finalize()
377+
}
378+
379+
fn _create_event(
380+
ref self: ContractState,
381+
name: ByteArray,
382+
symbol: ByteArray,
383+
uri: ByteArray,
384+
description: ByteArray,
385+
location: ByteArray,
386+
start_date: u64,
387+
end_date: u64,
388+
total_tickets: u256,
389+
ticket_price: u256,
390+
) -> EventData {
391+
let caller = get_caller_address();
392+
let event_count = self.event_count.read() + 1;
393+
let address_this = get_contract_address();
394+
395+
// create event role
396+
let event_hash = self._gen_event_hash(event_count);
397+
// grant caller event role
398+
self.accesscontrol._grant_role(event_hash, caller);
399+
400+
// deploy ticket721 contract
401+
let event_ticket = deploy_syscall(
402+
self.ticket_721_class_hash.read().try_into().unwrap(),
403+
event_hash,
404+
array![address_this.into(), address_this.into()].span(),
405+
true,
406+
);
407+
408+
let (event_ticket_addr, _) = event_ticket.unwrap_syscall();
409+
410+
// initialize ticket721 contract
411+
ITicket721Dispatcher { contract_address: event_ticket_addr }
412+
.initialize(name, symbol, uri,);
413+
414+
// new event struct instance
415+
let event_instance = EventData {
416+
id: event_count,
417+
organizer: caller,
418+
ticket_addr: event_ticket_addr,
419+
description: description,
420+
location: location,
421+
created_at: get_block_timestamp(),
422+
updated_at: 0,
423+
start_date: start_date,
424+
end_date: end_date,
425+
total_tickets: total_tickets,
426+
ticket_price: ticket_price,
427+
is_canceled: false,
428+
};
429+
430+
// Map event_id to new_event
431+
self.events.entry(event_count).write(event_instance);
432+
433+
// Update event count
434+
self.event_count.write(event_count);
435+
436+
// emit event for event creation
437+
self
438+
.emit(
439+
EventCreated {
440+
id: event_count, organizer: caller, ticket_address: event_ticket_addr
441+
}
442+
);
443+
444+
self.events.entry(event_count).read()
445+
}
446+
447+
fn _add_organizer(
448+
ref self: ContractState, event_hash: felt252, organizer: ContractAddress
449+
) {
450+
// grant role to caller
451+
self.accesscontrol._grant_role(event_hash, organizer);
452+
}
453+
454+
fn _remove_organizer(
455+
ref self: ContractState, event_hash: felt252, organizer: ContractAddress
456+
) {
457+
// revoke role from caller
458+
self.accesscontrol._revoke_role(event_hash, organizer);
459+
}
460+
}
416461
// #[generate_trait]
417462
// pub impl MultiCallImpl of IMultiCallTrait<ContractState> {
418463
// // Internal function to execute multiple calls

src/interfaces/i_event_factory.cairo

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ pub trait IEventFactory<TContractState> {
1414
end_date: u64,
1515
total_tickets: u256,
1616
ticket_price: u256,
17-
) -> bool;
17+
) -> EventData;
1818
fn update_event(
1919
ref self: TContractState,
2020
event_id: u256,
@@ -29,6 +29,8 @@ pub trait IEventFactory<TContractState> {
2929
ticket_price: u256,
3030
) -> bool;
3131
fn cancel_event(ref self: TContractState, event_id: u256) -> bool;
32+
fn add_organizer(ref self: TContractState, event_id: u256, organizer: ContractAddress);
33+
fn remove_organizer(ref self: TContractState, event_id: u256, organizer: ContractAddress);
3234
fn purchase_ticket(ref self: TContractState, event_id: u256) -> bool;
3335
fn get_all_events(self: @TContractState) -> Array<EventData>;
3436
fn get_event(self: @TContractState, event_id: u256) -> EventData;
@@ -41,8 +43,8 @@ pub trait IEventFactory<TContractState> {
4143
pub struct EventData {
4244
pub id: u256,
4345
pub organizer: ContractAddress,
44-
pub description: ByteArray,
4546
pub ticket_addr: ContractAddress,
47+
pub description: ByteArray,
4648
pub location: ByteArray,
4749
pub created_at: u64,
4850
pub updated_at: u64,

tests/test_event_factory.cairo

Lines changed: 30 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ fn deploy_event_factory() -> ContractAddress {
4242
event_factory_address
4343
}
4444

45-
fn create_event() -> (ContractAddress, bool, EventData, ITicket721Dispatcher,) {
45+
fn create_event() -> (ContractAddress, EventData, ITicket721Dispatcher,) {
4646
let event_factory_address = deploy_event_factory();
4747
let event_factory = IEventFactoryDispatcher { contract_address: event_factory_address };
4848

@@ -61,37 +61,36 @@ fn create_event() -> (ContractAddress, bool, EventData, ITicket721Dispatcher,) {
6161
100
6262
);
6363

64-
let event_data: EventData = event_factory.get_event(1);
65-
let evt_addr: ContractAddress = event_data.ticket_addr;
64+
let evt_addr: ContractAddress = event.ticket_addr;
6665
let event_ticket = ITicket721Dispatcher { contract_address: evt_addr };
67-
(event_factory_address, event, event_data, event_ticket)
66+
(event_factory_address, event, event_ticket)
6867
}
6968

7069
#[test]
7170
#[fork("SEPOLIA_LATEST")]
7271
fn test_create_event() {
73-
let (event_factory_address, event, event_data, event_ticket) = create_event();
72+
let (event_factory_address, event, event_ticket) = create_event();
7473
let event_factory = IEventFactoryDispatcher { contract_address: event_factory_address };
7574

76-
assert(event, 'Event creation failed');
77-
assert(event_factory.get_event_count() == 1, 'Invalid event count');
78-
assert(event_data.id == 1, 'Invalid event id');
79-
assert(event_data.organizer == ACCOUNT.try_into().unwrap(), 'Invalid organizer');
80-
assert(event_data.description == "Event Description", 'Invalid description');
81-
assert(event_data.location == "Event Location", 'Invalid location');
82-
assert(event_data.start_date <= get_block_timestamp(), 'Invalid start date');
83-
assert(event_data.end_date <= get_block_timestamp() + 86400, 'Invalid end date');
84-
assert(event_data.total_tickets == 100, 'Invalid total tickets');
85-
assert(event_data.ticket_price == 100, 'Invalid ticket price');
86-
assert(event_ticket.total_supply() == 0, 'Invalid total supply');
87-
assert(event_ticket.name() == "Event Name", 'Invalid name');
88-
assert(event_ticket.symbol() == "Event Symbol", 'Invalid symbol');
75+
// assert(event, 'Event creation failed');
76+
assert_eq!(event_factory.get_event_count(), 1);
77+
assert_eq!(event.id, 1);
78+
assert_eq!(event.organizer, ACCOUNT.try_into().unwrap());
79+
assert_eq!(event.description, "Event Description");
80+
assert_eq!(event.location, "Event Location");
81+
assert(event.start_date <= get_block_timestamp(), 'Invalid start date');
82+
assert(event.end_date <= get_block_timestamp() + 86400, 'Invalid end date');
83+
assert_eq!(event.total_tickets, 100);
84+
assert_eq!(event.ticket_price, 100);
85+
assert_eq!(event_ticket.total_supply(), 0);
86+
assert_eq!(event_ticket.name(), "Event Name");
87+
assert_eq!(event_ticket.symbol(), "Event Symbol");
8988
}
9089

9190
#[test]
9291
#[fork("SEPOLIA_LATEST")]
9392
fn test_cancel_event() {
94-
let (event_factory_address, _, _, _) = create_event();
93+
let (event_factory_address, _, _) = create_event();
9594
let event_factory = IEventFactoryDispatcher { contract_address: event_factory_address };
9695

9796
let event_canceled = event_factory.cancel_event(1);
@@ -100,19 +99,21 @@ fn test_cancel_event() {
10099
assert(event_canceled, 'Event cancellation failed');
101100
assert(event_data.is_canceled == true, 'Event not canceled');
102101
}
103-
// #[test]
104-
// #[fork("SEPOLIA_LATEST")]
105-
// fn test_not_organizer_cancel_event() {
106-
// let (event_factory_address, _, _, _) = create_event();
107-
// let event_factory = IEventFactoryDispatcher { contract_address: event_factory_address };
108102

109-
// let event_canceled = event_factory.cancel_event(1);
110-
// let event_data: EventData = event_factory.get_event(1);
103+
#[test]
104+
#[fork("SEPOLIA_LATEST")]
105+
#[should_panic(expected: 'Caller not main organizer')]
106+
fn test_not_main_organizer_cancel_event() {
107+
let (event_factory_address, _, _) = create_event();
108+
let event_factory = IEventFactoryDispatcher { contract_address: event_factory_address };
111109

112-
// assert(event_canceled, 'Event cancellation failed');
113-
// assert(event_data.is_canceled == true, 'Event not canceled');
114-
// }
110+
event_factory.add_organizer(1, ACCOUNT1.try_into().unwrap());
111+
stop_cheat_caller_address(event_factory_address);
112+
113+
start_cheat_caller_address(event_factory_address, ACCOUNT1.try_into().unwrap());
115114

115+
let event_canceled = event_factory.cancel_event(1);
116+
}
116117
// #[test]
117118
// fn test_increase_balance() {
118119
// let contract_address = deploy_contract("EventFactory");

0 commit comments

Comments
 (0)