Skip to content
Open
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
58 changes: 58 additions & 0 deletions src/components/sales.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#[starknet::component]
pub mod SalesComponent {
use starknet::storage::{
Map, StoragePathEntry, StoragePointerReadAccess, StoragePointerWriteAccess,
};
use crate::interfaces::{SalesStatus, SaleEvent};
use starknet::{ContractAddress, get_caller_address};
use crate::interfaces::sales::ISales;

#[storage]
pub struct Storage {
pub sales: Map<u256, SalesStatus>,
}

#[event]
#[derive(Drop, starknet::Event)]
pub enum Event {
SaleEvent: SaleEvent
}

#[embeddable_as(SalesImpl)]
pub impl Sales<
TContractState, +HasComponent<TContractState>,
> of ISales<ComponentState<TContractState>> {
fn buy(ref self: ComponentState<TContractState>, item_id: u256) {
let caller = get_caller_address();
let current_status = self.sales.read(item_id);

assert(
current_status == SalesStatus::None ||
matches!(current_status, SalesStatus::Sold(_)),
'Item not available for purchase'
);

self.sales.write(item_id, SalesStatus::Bought(caller));
self.emit(SaleEvent { item_id, status: SalesStatus::Bought(caller), caller });
}

fn sell(ref self: ComponentState<TContractState>, item_id: u256) {
let caller = get_caller_address();
let current_status = self.sales.read(item_id);

assert(
current_status == SalesStatus::None ||
(matches!(current_status, SalesStatus::Bought(owner)) && owner == caller),
'You cannot sell this item'
);

self.sales.write(item_id, SalesStatus::Sold(caller));
self.emit(SaleEvent { item_id, status: SalesStatus::Sold(caller), caller });
}


fn get_status(self: @ComponentState<TContractState>, item_id: u256) -> SalesStatus {
self.sales.read(item_id)
}
}
}
16 changes: 14 additions & 2 deletions src/components/voting.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ pub mod VotingComponent {
Map, StoragePathEntry, StoragePointerReadAccess, StoragePointerWriteAccess,
};
use starknet::{ContractAddress, get_caller_address};
use crate::components::sales::{SalesImpl, SalesStatus};
use crate::interfaces::voting::{DEFAULT_THRESHOLD, IVote, Poll, PollTrait, Voted};

#[storage]
pub struct Storage {
pub polls: Map<u256, Poll>,
pub voters: Map<(ContractAddress, u256), bool>,
pub nonce: u256,
pub sales: SalesImpl,
}

#[event]
Expand All @@ -24,13 +26,14 @@ pub mod VotingComponent {
TContractState, +HasComponent<TContractState>,
> of IVote<ComponentState<TContractState>> {
fn create_poll(
ref self: ComponentState<TContractState>, name: ByteArray, desc: ByteArray,
ref self: ComponentState<TContractState>, name: ByteArray, desc: ByteArray,item_id: u256
) -> u256 {
let id = self.nonce.read() + 1;
assert(name != "" && desc != "", 'NAME OR DESC IS EMPTY');
let mut poll: Poll = Default::default();
poll.name = name;
poll.desc = desc;
poll.linked_item = item_id;
self.polls.entry(id).write(poll);
self.nonce.write(id);
id
Expand All @@ -46,7 +49,16 @@ pub mod VotingComponent {

match support {
true => poll.yes_votes += 1,
_ => poll.no_votes += 1,
false => {
poll.no_votes += 1;
// Check if this "no" vote caused the threshold to be reached
let vote_count = poll.yes_votes + poll.no_votes;
if vote_count >= DEFAULT_THRESHOLD && poll.no_votes > poll.yes_votes {
// Immediately trigger sale if voting failed
self.sales.sell(poll.linked_item);
poll.status = PollStatus::Finished(false);
}
}
}

let vote_count = poll.yes_votes + poll.no_votes;
Expand Down
24 changes: 24 additions & 0 deletions src/interfaces/sales.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use starknet::ContractAddress;

#[starknet::interface]
pub trait ISales<TContractState> {
fn buy(ref self: TContractState, item_id: u256);
fn sell(ref self: TContractState, item_id: u256);
fn get_status(self: @TContractState, item_id: u256) -> SalesStatus;
}

#[derive(Drop, Copy, Serde, starknet::Store, PartialEq)]
pub enum SalesStatus {
#[default]
None,
Bought: ContractAddress,
Sold: ContractAddress
}

#[derive(Drop, starknet::Event)]
pub struct SaleEvent {
#[key]
pub item_id: u256,
pub status: SalesStatus,
pub caller: ContractAddress
}
1 change: 1 addition & 0 deletions src/interfaces/voting.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pub struct Poll {
pub yes_votes: u256,
pub no_votes: u256,
pub status: PollStatus,
pub linked_item: u256,
}

#[generate_trait]
Expand Down
2 changes: 2 additions & 0 deletions src/lib.cairo
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
pub mod interfaces {
pub mod voting;
pub mod sales;
}

pub mod components {
pub mod voting;
pub mod sales;
}

pub mod mock_contract;
12 changes: 11 additions & 1 deletion src/mock_contract.cairo
Original file line number Diff line number Diff line change
@@ -1,20 +1,30 @@
#[starknet::contract]
pub mod MockContract {
use crate::components::voting::VotingComponent;
use crate::components::sales::SalesComponent;

#[abi(embed_v0)]
pub impl VotingImpl = VotingComponent::VotingImpl<ContractState>;

#[abi(embed_v0)]
pub impl SalesImpl = SalesComponent::SalesImpl<ContractState>;

#[storage]
pub struct Storage {
#[substorage(v0)]
pub voting: VotingComponent::Storage,
#[substorage(v0)]
pub sales: SalesComponent::Storage,
}

#[event]
#[derive(Drop, starknet::Event)]
pub enum Event {
#[flat]
VotingEvent: VotingComponent::Event,
}

#[flat]
SalesEvent: SalesComponent::Event,
}

}