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
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ git clone https://github.com/openguild-labs/frame-challenges.git

Go to **Participant Registration** section and register to be the workshop participants. Add the below to the list, replace any placeholder with your personal information.

```
| 🦄 | Name | Github username | Your current occupation |
```
| Emoji | Name | GitHub Username | Current Occupation |
|:-----:|------------------------|----------------|----------------------|
| 🔥 | Kurniadi Ahmad Wijaya | [ShinyQ](https://github.com/ShinyQ) | Software Engineer |

- Step 5: `Commit` your code and push to the forked Github repository

Expand Down
71 changes: 63 additions & 8 deletions src/governance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@ use std::collections::HashMap;

pub trait GovernanceConfig: StakingConfig {}

pub struct Proposal {
pub struct Proposal<T: GovernanceConfig> {
description: String,
yes_votes: u32,
no_votes: u32,
status: ProposalStatus,
creator: T::AccountId,
}

#[derive(Clone)]
Expand All @@ -19,14 +20,18 @@ pub enum ProposalStatus {
}

pub struct GovernancePallet<T: GovernanceConfig> {
pub proposals: HashMap<u32, Proposal>,
pub proposals: HashMap<u32, Proposal<T>>,
pub votes: HashMap<(T::AccountId, u32), bool>, // (voter, proposal_id) -> vote_type
next_proposal_id: u32,
}

impl<T: GovernanceConfig> GovernancePallet<T> {
pub fn new() -> Self {
todo!()
Self {
proposals: HashMap::new(),
votes: HashMap::new(),
next_proposal_id: 0,
}
}

// Create a new proposal
Expand All @@ -35,7 +40,22 @@ impl<T: GovernanceConfig> GovernancePallet<T> {
creator: T::AccountId,
description: String,
) -> Result<u32, &'static str> {
todo!()
let proposal_id = self.next_proposal_id;

self.proposals.insert(
proposal_id,
Proposal {
description,
yes_votes: 0,
no_votes: 0,
status: ProposalStatus::Active,
creator
},
);

self.next_proposal_id += 1;

Ok(proposal_id)
}

// Vote on a proposal (true = yes, false = no)
Expand All @@ -45,17 +65,50 @@ impl<T: GovernanceConfig> GovernancePallet<T> {
proposal_id: u32,
vote_type: bool,
) -> Result<(), &'static str> {
todo!()
let proposal = self.proposals.get_mut(&proposal_id)
.ok_or("Proposal does not exist")?;

if !matches!(proposal.status, ProposalStatus::Active) {
return Err("Cannot vote on finalized proposal");
}

let vote_key = (voter.clone(), proposal_id);

if self.votes.insert(vote_key, vote_type).is_some() {
return Err("Voter has already voted on this proposal");
}

if vote_type {
proposal.yes_votes += 1;
} else {
proposal.no_votes += 1;
}

Ok(())
}

// Get proposal details
pub fn get_proposal(&self, proposal_id: u32) -> Option<&Proposal> {
todo!()
pub fn get_proposal(&self, proposal_id: u32) -> Option<&Proposal<T>> {
self.proposals.get(&proposal_id)
}

// Finalize a proposal (changes status based on votes)
pub fn finalize_proposal(&mut self, proposal_id: u32) -> Result<ProposalStatus, &'static str> {
todo!()
let proposal = self.proposals
.get_mut(&proposal_id)
.ok_or("Proposal does not exist")?;

if !matches!(proposal.status, ProposalStatus::Active) {
return Err("Cannot vote on finalized proposal");
}

proposal.status = if proposal.yes_votes > proposal.no_votes {
ProposalStatus::Approved
} else {
ProposalStatus::Rejected
};

Ok(proposal.status.clone())
}
}

Expand Down Expand Up @@ -86,6 +139,8 @@ mod tests {
let proposal = governance.get_proposal(proposal_id).unwrap();
assert_eq!(proposal.yes_votes, 2);
assert_eq!(proposal.no_votes, 1);
assert_eq!(proposal.description, "Increase validator rewards".to_string());
assert_eq!(proposal.creator, alice);

// Finalize proposal
let status = governance.finalize_proposal(proposal_id).unwrap();
Expand Down
46 changes: 40 additions & 6 deletions src/staking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,32 +16,66 @@ pub struct StakingPallet<T: StakingConfig> {

impl<T: StakingConfig> StakingPallet<T> {
pub fn new() -> Self {
todo!()
Self {
free_balances: HashMap::new(),
staked_balances: HashMap::new(),
}
}

// Set free balance for an account
pub fn set_balance(&mut self, who: T::AccountId, amount: T::Balance) {
todo!()
self.free_balances.insert(who, amount);
}

// Stake tokens (move from free to staked)
pub fn stake(&mut self, who: T::AccountId, amount: T::Balance) -> Result<(), &'static str> {
todo!()
let free_balance = self.free_balances.get(&who).copied()
.unwrap_or(T::Balance::zero());

let staked_balance = self.staked_balances.get(&who).copied()
.unwrap_or(T::Balance::zero());

let new_free = free_balance.checked_sub(&amount)
.ok_or("Insufficient balance")?;

let new_staked = staked_balance.checked_add(&amount)
.ok_or("Overflow")?;

self.free_balances.insert(who.clone(), new_free);
self.staked_balances.insert(who, new_staked);

Ok(())
}


// Unstake tokens (move from staked to free)
pub fn unstake(&mut self, who: T::AccountId, amount: T::Balance) -> Result<(), &'static str> {
todo!()
let staked_balance = self.staked_balances.get(&who).copied()
.unwrap_or(T::Balance::zero());

let free_balance = self.free_balances.get(&who).copied()
.unwrap_or(T::Balance::zero());

let new_staked = staked_balance.checked_sub(&amount)
.ok_or("Insufficient staked balance")?;

let new_free = free_balance.checked_add(&amount)
.ok_or("Overflow")?;

self.staked_balances.insert(who.clone(), new_staked);
self.free_balances.insert(who, new_free);

Ok(())
}

// Get free balance for an account
pub fn get_free_balance(&self, who: T::AccountId) -> T::Balance {
todo!()
self.free_balances.get(&who).copied().unwrap_or(T::Balance::zero())
}

// Get staked balance for an account
pub fn get_staked_balance(&self, who: T::AccountId) -> T::Balance {
todo!()
self.staked_balances.get(&who).copied().unwrap_or(T::Balance::zero())
}
}

Expand Down