Rise In Logo

Build on Internet Computer with ICP Rust CDK

Creating Functions 2

Creating Functions 2

Implementing Error Handling and the edit_proposal Function in Our Smart Contract

In our previous lesson, we built the initial query and update functions for our proposal system. In this lesson, we enhance our system by introducing robust error handling using enums, and we implement the logic for editing proposals.

Step 1: Defining Enumerations for Logic and Errors

Choice Enum

We define the Choice enum to represent a vote on a proposal. It includes:

  • Approve
  • Reject
  • Pass

Each of these choices will be used to update the corresponding vote count in a proposal.

#[derive(CandidType, Deserialize)]
pub enum Choice {
    Approve,
    Reject,
    Pass,
}

VoteError Enum

We introduce VoteError to handle various error scenarios in a structured manner:

#[derive(CandidType, Deserialize)]
pub enum VoteError {
    AlreadyVoted,
    ProposalIsNotActive,
    NoSuchProposal,
    AccessRejected,
    UpdateError,
}

These help signal issues such as unauthorized access, missing proposals, or unknown update failures.

Step 2: Implementing the edit_proposal Update Function

Only the creator (owner) of a proposal can edit it. Here's how the function works:

#[update]
fn edit_proposal(key: u64, new_data: CreateProposal) -> Result<(), VoteError> {
    PROPOSAL_MAP.with(|p| {
        let mut p = p.borrow_mut();

        // Retrieve existing proposal
        let old = match p.get(&key) {
            Some(proposal) => proposal.clone(),
            None => return Err(VoteError::NoSuchProposal),
        };

        // Check if the caller is the owner
        if ic_cdk::caller() != old.owner {
            return Err(VoteError::AccessRejected);
        }

        // Build updated proposal using the new description and is_active fields
        let updated = Proposal {
            description: new_data.description,
            approve: old.approve,
            reject: old.reject,
            pass: old.pass,
            is_active: new_data.is_active,
            voted: old.voted.clone(),
            owner: old.owner,
        };

        // Insert the updated proposal
        let result = p.insert(key, updated);

        match result {
            Some(_) => Ok(()),
            None => Err(VoteError::UpdateError),
        }
    })
}

Step 3: Summary of Logic

  1. Retrieve Proposal: Check if the proposal with the given key exists. If not, return NoSuchProposal.
  2. Verify Ownership: Ensure that the caller is the original creator. If not, return AccessRejected.
  3. Update Only Relevant Fields: Only description and is_active fields are updated; all others are preserved to maintain integrity.
  4. Insert Updated Proposal: Replace the existing proposal in the map and handle potential errors.

Comments

You need to enroll in the course to be able to comment!

Stay in the know

Never miss updates on new programs and opportunities.

Rise In Logo

Rise together in web3!

Disclaimer: The information /programs / events provided on https://patika.dev and https://risein.com are strictly for upskilling and networking purposes related to the technical infrastructure of blockchain platforms. We do not provide financial or investment advice and do not make any representations regarding the value, profitability, or future price of any blockchain or cryptocurrency. Users are encouraged to conduct their own research and consult with licensed financial professionals before engaging in any investment activities. https://patika.dev and https://risein.com disclaim any responsibility for financial decisions made by users based on information provided here.