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
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use contract_::audition::types::season_and_audition::{
Appeal, ArtistRegistration, Audition, Evaluation, Genre, RegistrationConfig, Season, Vote,
Appeal, Audition, Evaluation, Genre, RegistrationConfig, Season, Vote,
};
use starknet::ContractAddress;

Expand Down
88 changes: 58 additions & 30 deletions contract_/src/audition/season_and_audition.cairo
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
#[starknet::contract]
pub mod SeasonAndAudition {
use OwnableComponent::{HasComponent, InternalTrait};
use OwnableComponent::InternalTrait;
use contract_::audition::interfaces::iseason_and_audition::ISeasonAndAudition;
use contract_::audition::types::season_and_audition::{
Appeal, ArtistRegistration, Audition, Evaluation, Genre, RegistrationConfig, Season, Vote,
};
use contract_::errors::errors;
use core::num::traits::Zero;
use openzeppelin::access::accesscontrol::{AccessControlComponent, DEFAULT_ADMIN_ROLE};
use openzeppelin::access::ownable::OwnableComponent;
use openzeppelin::introspection::src5::SRC5Component;
use openzeppelin::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait};
use starknet::event::EventEmitter;
use starknet::storage::{
Expand All @@ -27,17 +29,36 @@ pub mod SeasonAndAudition {

// Integrates OpenZeppelin ownership component
component!(path: OwnableComponent, storage: ownable, event: OwnableEvent);
component!(path: AccessControlComponent, storage: accesscontrol, event: AccessControlEvent);
component!(path: SRC5Component, storage: src5, event: SRC5Event);

// @notice the precision for the score
const PRECISION: u256 = 100;

const ADMIN_ROLE: felt252 = selector!("ADMIN_ROLE");
const SEASON_MAINTAINER_ROLE: felt252 = selector!("SEASON_MAINTAINER_ROLE");
const AUDITION_MAINTAINER_ROLE: felt252 = selector!("AUDITION_MAINTAINER_ROLE");
const REVIEWER_ROLE: felt252 = selector!("REVIEWER_ROLE");

#[abi(embed_v0)]
impl OwnableMixinImpl = OwnableComponent::OwnableMixinImpl<ContractState>;
impl OwnableTwoStepImpl = OwnableComponent::OwnableTwoStepImpl<ContractState>;
impl OwnableImpl = OwnableComponent::OwnableImpl<ContractState>;

#[abi(embed_v0)]
impl AccessControlImpl =
AccessControlComponent::AccessControlImpl<ContractState>;
impl AccessControlInternalImpl = AccessControlComponent::InternalImpl<ContractState>;

#[abi(embed_v0)]
impl SRC5Impl = SRC5Component::SRC5Impl<ContractState>;

#[storage]
struct Storage {
#[substorage(v0)]
accesscontrol: AccessControlComponent::Storage,
#[substorage(v0)]
src5: SRC5Component::Storage,
whitelisted_oracles: Map<ContractAddress, bool>,
seasons: Map<u256, Season>,
season_count: u256,
Expand Down Expand Up @@ -159,6 +180,10 @@ pub mod SeasonAndAudition {
ResumedAll: ResumedAll,
#[flat]
OwnableEvent: OwnableComponent::Event,
#[flat]
AccessControlEvent: AccessControlComponent::Event,
#[flat]
SRC5Event: SRC5Component::Event,
PriceDeposited: PriceDeposited,
PriceDistributed: PriceDistributed,
JudgeAdded: JudgeAdded,
Expand All @@ -182,12 +207,21 @@ pub mod SeasonAndAudition {
self.ownable.initializer(owner);
self.global_paused.write(false);
self.judging_paused.write(false);
self.accesscontrol.initializer();
self.accesscontrol.set_role_admin(SEASON_MAINTAINER_ROLE, ADMIN_ROLE);
self.accesscontrol.set_role_admin(AUDITION_MAINTAINER_ROLE, ADMIN_ROLE);
self.accesscontrol.set_role_admin(REVIEWER_ROLE, ADMIN_ROLE);
self.accesscontrol._grant_role(ADMIN_ROLE, owner);
self.accesscontrol._grant_role(DEFAULT_ADMIN_ROLE, owner);
self.accesscontrol._grant_role(SEASON_MAINTAINER_ROLE, owner);
self.accesscontrol._grant_role(AUDITION_MAINTAINER_ROLE, owner);
self.accesscontrol._grant_role(REVIEWER_ROLE, owner);
}

#[abi(embed_v0)]
impl ISeasonAndAuditionImpl of ISeasonAndAudition<ContractState> {
fn create_season(ref self: ContractState, name: felt252, start_time: u64, end_time: u64) {
self.ownable.assert_only_owner();
self.accesscontrol.assert_only_role(SEASON_MAINTAINER_ROLE);
self.assert_all_seasons_closed();
self.assert_valid_time(start_time, end_time);
assert(!self.global_paused.read(), 'Contract is paused');
Expand Down Expand Up @@ -225,7 +259,7 @@ pub mod SeasonAndAudition {
fn update_season(
ref self: ContractState, season_id: u256, name: Option<felt252>, end_time: Option<u64>,
) {
self.ownable.assert_only_owner();
self.accesscontrol.assert_only_role(SEASON_MAINTAINER_ROLE);
self.assert_valid_season(season_id);
assert(!self.global_paused.read(), 'Contract is paused');

Expand Down Expand Up @@ -253,7 +287,7 @@ pub mod SeasonAndAudition {
fn create_audition(
ref self: ContractState, name: felt252, genre: Genre, end_timestamp: u64,
) {
self.ownable.assert_only_owner();
self.accesscontrol.assert_only_role(AUDITION_MAINTAINER_ROLE);
assert(!self.global_paused.read(), 'Contract is paused');
let season_id = self.active_season.read().expect('No active season');
self.assert_valid_season(season_id);
Expand Down Expand Up @@ -293,7 +327,7 @@ pub mod SeasonAndAudition {
name: Option<felt252>,
genre: Option<Genre>,
) {
self.ownable.assert_only_owner();
self.accesscontrol.assert_only_role(AUDITION_MAINTAINER_ROLE);
assert(!self.global_paused.read(), 'Contract is paused');
self.assert_valid_audition(audition_id);
let mut audition = self.auditions.entry(audition_id).read();
Expand Down Expand Up @@ -327,7 +361,7 @@ pub mod SeasonAndAudition {
fn update_registration_config(
ref self: ContractState, audition_id: u256, config: RegistrationConfig,
) {
self.ownable.assert_only_owner();
self.accesscontrol.assert_only_role(SEASON_MAINTAINER_ROLE);
assert(self.audition_exists(audition_id), 'Audition does not exist');
assert(!self.is_audition_ended(audition_id), 'Audition already ended');
assert(!self.registration_started.entry(audition_id).read(), 'Registration Started');
Expand Down Expand Up @@ -403,7 +437,7 @@ pub mod SeasonAndAudition {
fn set_evaluation_weight(
ref self: ContractState, audition_id: u256, weight: (u256, u256, u256),
) {
self.ownable.assert_only_owner();
self.accesscontrol.assert_only_role(AUDITION_MAINTAINER_ROLE);
assert(!self.global_paused.read(), 'Contract is paused');
assert(self.audition_exists(audition_id), 'Audition does not exist');
assert(!self.is_audition_ended(audition_id), 'Audition has ended');
Expand Down Expand Up @@ -432,7 +466,7 @@ pub mod SeasonAndAudition {
}

fn perform_aggregate_score_calculation(ref self: ContractState, audition_id: u256) {
self.ownable.assert_only_owner();
self.accesscontrol.assert_only_role(AUDITION_MAINTAINER_ROLE);
assert(!self.global_paused.read(), 'Contract is paused');
assert(self.audition_exists(audition_id), 'Audition does not exist');
assert(self.is_audition_ended(audition_id), 'Audition has not ended');
Expand Down Expand Up @@ -516,7 +550,7 @@ pub mod SeasonAndAudition {
/// @param audition_id the id of the audition to add the judge to
/// @param judge_address the address of the judge to add
fn add_judge(ref self: ContractState, audition_id: u256, judge_address: ContractAddress) {
self.ownable.assert_only_owner();
self.accesscontrol.assert_only_role(AUDITION_MAINTAINER_ROLE);
assert(!self.global_paused.read(), 'Contract is paused');
assert(self.audition_exists(audition_id), 'Audition does not exist');
assert(!self.is_audition_ended(audition_id), 'Audition has already ended');
Expand All @@ -538,7 +572,7 @@ pub mod SeasonAndAudition {
fn remove_judge(
ref self: ContractState, audition_id: u256, judge_address: ContractAddress,
) {
self.ownable.assert_only_owner();
self.accesscontrol.assert_only_role(AUDITION_MAINTAINER_ROLE);
assert(!self.global_paused.read(), 'Contract is paused');
assert(self.audition_exists(audition_id), 'Audition does not exist');
assert(!self.is_audition_ended(audition_id), 'Audition has ended');
Expand Down Expand Up @@ -658,12 +692,12 @@ pub mod SeasonAndAudition {


fn pause_judging(ref self: ContractState) {
self.ownable.assert_only_owner();
self.accesscontrol.assert_only_role(AUDITION_MAINTAINER_ROLE);
self.judging_paused.write(true);
}

fn resume_judging(ref self: ContractState) {
self.ownable.assert_only_owner();
self.accesscontrol.assert_only_role(AUDITION_MAINTAINER_ROLE);
self.judging_paused.write(false);
}

Expand All @@ -675,7 +709,7 @@ pub mod SeasonAndAudition {
fn submit_result(
ref self: ContractState, audition_id: u256, result_uri: ByteArray, performer_id: u256,
) {
self.ownable.assert_only_owner();
self.accesscontrol.assert_only_role(REVIEWER_ROLE);
let audition = self.auditions.entry(audition_id).read();
self.assert_valid_season(audition.season_id);
assert(!self.global_paused.read(), 'Contract is paused');
Expand Down Expand Up @@ -756,7 +790,7 @@ pub mod SeasonAndAudition {
token_address: ContractAddress,
amount: u256,
) {
self.ownable.assert_only_owner();
self.accesscontrol.assert_only_role(ADMIN_ROLE);
assert(!self.global_paused.read(), 'Contract is paused');
assert(self.audition_exists(audition_id), 'Audition does not exist');
assert(!self.is_audition_ended(audition_id), 'Audition has already ended');
Expand Down Expand Up @@ -911,13 +945,13 @@ pub mod SeasonAndAudition {
}

fn pause_all(ref self: ContractState) {
self.ownable.assert_only_owner();
self.accesscontrol.assert_only_role(ADMIN_ROLE);
self.global_paused.write(true);
self.emit(Event::PausedAll(PausedAll { timestamp: get_block_timestamp() }));
}

fn resume_all(ref self: ContractState) {
self.ownable.assert_only_owner();
self.accesscontrol.assert_only_role(ADMIN_ROLE);
self.global_paused.write(false);
self.emit(Event::ResumedAll(ResumedAll { timestamp: get_block_timestamp() }));
}
Expand All @@ -927,7 +961,7 @@ pub mod SeasonAndAudition {
}

fn pause_audition(ref self: ContractState, audition_id: u256) -> bool {
self.ownable.assert_only_owner();
self.accesscontrol.assert_only_role(AUDITION_MAINTAINER_ROLE);
assert(!self.global_paused.read(), 'Contract is paused');
let audition = self.auditions.entry(audition_id).read();
self.assert_valid_season(audition.season_id);
Expand All @@ -947,7 +981,7 @@ pub mod SeasonAndAudition {
}

fn resume_audition(ref self: ContractState, audition_id: u256) -> bool {
self.ownable.assert_only_owner();
self.accesscontrol.assert_only_role(AUDITION_MAINTAINER_ROLE);
assert(!self.global_paused.read(), 'Contract is paused');
assert(self.audition_exists(audition_id), 'Audition does not exist');
assert(self.is_audition_paused(audition_id), 'Audition is not paused');
Expand All @@ -966,7 +1000,7 @@ pub mod SeasonAndAudition {
}

fn end_audition(ref self: ContractState, audition_id: u256) -> bool {
self.ownable.assert_only_owner();
self.accesscontrol.assert_only_role(ADMIN_ROLE);
assert(!self.global_paused.read(), 'Contract is paused');

assert(self.audition_exists(audition_id), 'Audition does not exist');
Expand Down Expand Up @@ -1014,7 +1048,7 @@ pub mod SeasonAndAudition {


fn pause_season(ref self: ContractState, season_id: u256) {
self.ownable.assert_only_owner();
self.accesscontrol.assert_only_role(SEASON_MAINTAINER_ROLE);
assert(!self.global_paused.read(), 'Contract is paused');
self.assert_valid_season(season_id);
let mut season = self.seasons.entry(season_id).read();
Expand All @@ -1029,7 +1063,7 @@ pub mod SeasonAndAudition {
);
}
fn resume_season(ref self: ContractState, season_id: u256) {
self.ownable.assert_only_owner();
self.accesscontrol.assert_only_role(SEASON_MAINTAINER_ROLE);
assert(!self.global_paused.read(), 'Contract is paused');
assert(self.season_exists(season_id), 'Season does not exist');
let mut season = self.seasons.entry(season_id).read();
Expand Down Expand Up @@ -1069,7 +1103,7 @@ pub mod SeasonAndAudition {
}

fn end_season(ref self: ContractState, season_id: u256) {
self.ownable.assert_only_owner();
self.accesscontrol.assert_only_role(SEASON_MAINTAINER_ROLE);
assert(!self.global_paused.read(), 'Contract is paused');
assert(self.season_exists(season_id), 'Season does not exist');
assert(self.is_season_ended(season_id), 'Season has not ended');
Expand Down Expand Up @@ -1201,7 +1235,7 @@ pub mod SeasonAndAudition {
// Only owner or judge can resolve
let evaluation = self.evaluations.entry(evaluation_id).read();
let audition_id = evaluation.audition_id;
self.ownable.assert_only_owner();
self.accesscontrol.assert_only_role(AUDITION_MAINTAINER_ROLE);
let mut is_judge = false;
let judges = self.get_judges(audition_id);
for judge in judges {
Expand Down Expand Up @@ -1315,19 +1349,13 @@ pub mod SeasonAndAudition {
/// @param winners An array of 3 contract addresses representing the winners.
/// @param shares An array of 3 u256 values representing the share percentages for each
/// winner.
/// @custom:reverts If called by anyone other than the owner.
/// @custom:reverts If the contract is paused.
/// @custom:reverts If the audition does not exist or has not ended.
/// @custom:reverts If there is no prize for the audition.
/// @custom:reverts If any winner address is zero.
/// @custom:reverts If the total shares do not add up to 100.
fn assert_distributed(
ref self: ContractState,
audition_id: u256,
winners: [ContractAddress; 3],
shares: [u256; 3],
) {
self.ownable.assert_only_owner();
self.accesscontrol.assert_only_role(AUDITION_MAINTAINER_ROLE);
assert(!self.global_paused.read(), 'Contract is paused');
assert(self.audition_exists(audition_id), 'Audition does not exist');
assert(self.is_audition_ended(audition_id), 'Audition must end first');
Expand Down
1 change: 0 additions & 1 deletion contract_/src/audition/stake_to_vote.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ pub mod StakeToVote {
ISeasonAndAuditionDispatcher, ISeasonAndAuditionDispatcherTrait,
};
use contract_::audition::interfaces::istake_to_vote::IStakeToVote;
use contract_::audition::types::season_and_audition::Audition;
use contract_::audition::types::stake_to_vote::*;
use contract_::errors::errors;
use core::num::traits::Zero;
Expand Down
1 change: 0 additions & 1 deletion contract_/src/audition/stake_withdrawal.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ pub mod StakeWithdrawal {
use contract_::audition::interfaces::istake_to_vote::{
IStakeToVoteDispatcher, IStakeToVoteDispatcherTrait,
};
use contract_::audition::types::season_and_audition::Audition;
use contract_::audition::types::stake_to_vote::{StakerInfo, StakingConfig};
use core::num::traits::Zero;
use openzeppelin::access::ownable::OwnableComponent;
Expand Down
10 changes: 5 additions & 5 deletions contract_/src/governance/ProposalSystem.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,11 @@ pub mod ProposalSystem {
Map, StorageMapReadAccess, StorageMapWriteAccess, StoragePointerReadAccess,
StoragePointerWriteAccess,
};
use starknet::{
ContractAddress, contract_address_const, get_block_timestamp, get_caller_address,
};
use starknet::{ContractAddress, get_block_timestamp, get_caller_address};
use super::*;

const zero_address: ContractAddress = 0.try_into().unwrap();

#[storage]
struct Storage {
proposals: Map<u64, Proposal>,
Expand Down Expand Up @@ -237,7 +237,7 @@ pub mod ProposalSystem {
let proposal = self.proposals.read(current_id);

// Apply filters
let matches_token = token_contract == contract_address_const::<0>()
let matches_token = token_contract == zero_address
|| proposal.token_contract == token_contract;
let matches_status = status == 255_u8 || proposal.status == status;
let matches_category = category == 'ALL' || proposal.category == category;
Expand Down Expand Up @@ -475,7 +475,7 @@ pub mod ProposalSystem {
let current_artist = self.artists.read(token_contract);

// If no registered artist, register artist linked to token in factory contract
if current_artist == contract_address_const::<0>() {
if current_artist == zero_address {
let factory_dispatcher = IMusicShareTokenFactoryDispatcher {
contract_address: self.factory_contract.read(),
};
Expand Down
Loading
Loading