In the previous video, we built the edit_proposal function. In this lesson, we finalize the smart contract by implementing the remaining two core update functions: end_proposal and vote. These complete the functionality of our decentralized voting system.
This function deactivates a proposal, preventing further votes.
#[update]
fn end_proposal(key: u64) -> Result<(), VoteError> {
PROPOSAL_MAP.with(|p| {
let mut p = p.borrow_mut();
let proposal = match p.get(&key) {
Some(p) => p.clone(),
None => return Err(VoteError::NoSuchProposal),
};
if ic_cdk::caller() != proposal.owner {
return Err(VoteError::AccessRejected);
}
let mut updated = proposal;
updated.is_active = false;
let result = p.insert(key, updated);
match result {
Some(_) => Ok(()),
None => Err(VoteError::UpdateError),
}
})
}
This function allows users to cast a vote (approve, reject, or pass) on an active proposal.
#[update]
fn vote(key: u64, choice: Choice) -> Result<(), VoteError> {
PROPOSAL_MAP.with(|p| {
let mut p = p.borrow_mut();
let mut proposal = match p.get(&key) {
Some(p) => p.clone(),
None => return Err(VoteError::NoSuchProposal),
};
let caller = ic_cdk::caller();
if proposal.voted.contains(&caller) {
return Err(VoteError::AlreadyVoted);
}
if !proposal.is_active {
return Err(VoteError::ProposalIsNotActive);
}
match choice {
Choice::Approve => proposal.approve += 1,
Choice::Reject => proposal.reject += 1,
Choice::Pass => proposal.pass += 1,
}
proposal.voted.push(caller);
let result = p.insert(key, proposal);
match result {
Some(_) => Ok(()),
None => Err(VoteError::UpdateError),
}
})
}
With the addition of end_proposal and vote, your voting smart contract is now complete. Each function follows a consistent pattern:
This pattern ensures the contract is secure, maintainable, and easy to understand.
Swap insights and ask questions about “Build on Internet Computer with ICP Rust CDK”.
Ask a question or share your thoughts about this lesson.