Running into an issue while working on a NEAR contract. Facing multiple errors, including traits not being implemented for UnorderedSet<AccountId> and mismatched types

Running into an issue while working on a NEAR contract. Facing multiple errors, including traits not being implemented for UnorderedSet<AccountId> and mismatched types.

error[E0277]: the trait bound `UnorderedSet<AccountId>: Default` is not satisfied
  --> src/lib.rs:38:55
   |
38 | #[derive(BorshDeserialize, BorshSerialize, Serialize, Deserialize, Clone)]
   |                                                       ^^^^^^^^^^^ the trait `Default` is not implemented for `UnorderedSet<AccountId>`
   |
   = note: this error originates in the derive macro `Deserialize` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: the trait bound `UnorderedSet<AccountId>: Clone` is not satisfied
  --> src/lib.rs:48:5
   |
38 | #[derive(BorshDeserialize, BorshSerialize, Serialize, Deserialize, Clone)]
   |                                                                    ----- in this derive macro expansion
...
48 |     voters: UnorderedSet<AccountId>,
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `UnorderedSet<AccountId>`
   |
   = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0308]: mismatched types
   --> src/lib.rs:85:25
    |
85  |         self.tokens.get(account_id).map(|token| token.metadata.clone())
    |                     --- ^^^^^^^^^^ expected `&_`, found `AccountId`
    |                     |
    |                     arguments to this method are incorrect
    |
    = note: expected reference `&_`
                  found struct `AccountId`
note: method defined here
   --> /home/akash/.cargo/registry/src/index.crates.io-6f17d22bba15001f/near-sdk-5.5.0/src/store/lookup_map/mod.rs:242:12
    |
242 |     pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V>
    |            ^^^
help: consider borrowing here
    |
85  |         self.tokens.get(&account_id).map(|token| token.metadata.clone())
    |                         +

error[E0308]: mismatched types
   --> src/lib.rs:144:44
    |
144 |         self.proposals.insert(proposal_id, &proposal);
    |                        ------              ^^^^^^^^^ expected `Proposal`, found `&&Proposal`
    |                        |
    |                        arguments to this method are incorrect
    |
help: the return type of this call is `&&Proposal` due to the type of the argument passed
   --> src/lib.rs:144:9
    |
144 |         self.proposals.insert(proposal_id, &proposal);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------^
    |                                            |
    |                                            this argument influences the return type of `insert`
note: method defined here
   --> /home/akash/.cargo/registry/src/index.crates.io-6f17d22bba15001f/near-sdk-5.5.0/src/store/unordered_map/mod.rs:487:12
    |
487 |     pub fn insert(&mut self, k: K, value: V) -> Option<V>
    |            ^^^^^^

error[E0308]: mismatched types
   --> src/lib.rs:148:9
    |
147 |     pub fn get_proposal(&self, proposal_id: u64) -> Option<Proposal> {
    |                                                     ---------------- expected `std::option::Option<Proposal>` because of return type
148 |         self.proposals.get(&proposal_id)
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Option<Proposal>`, found `Option<&Proposal>`
    |
    = note: expected enum `std::option::Option<Proposal>`
               found enum `std::option::Option<&Proposal>`
help: use `std::option::Option::cloned` to clone the value inside the `std::option::Option`
    |
148 |         self.proposals.get(&proposal_id).cloned()
    |                                         +++++++++

error[E0277]: a value of type `Vec<Proposal>` cannot be built from an iterator over elements of type `&Proposal`
   --> src/lib.rs:152:33
    |
152 |         self.proposals.values().collect()
    |                                 ^^^^^^^ value of type `Vec<Proposal>` cannot be built from `std::iter::Iterator<Item=&Proposal>`
    |
    = help: the trait `FromIterator<&Proposal>` is not implemented for `Vec<Proposal>`
    = help: the trait `FromIterator<Proposal>` is implemented for `Vec<Proposal>`
    = help: for that trait implementation, expected `Proposal`, found `&Proposal`
note: the method call chain might not have had the expected associated types
   --> src/lib.rs:152:24
    |
152 |         self.proposals.values().collect()
    |         -------------- ^^^^^^^^ `Iterator::Item` is `&Proposal` here
    |         |
    |         this expression has type `UnorderedMap<u64, Proposal>`
note: required by a bound in `collect`
   --> /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/core/src/iter/traits/iterator.rs:2001:5

error[E0382]: use of moved value: `account_id`
  --> src/lib.rs:81:34
   |
72 |     pub fn mint(&mut self, account_id: AccountId, metadata: TokenMetadata) {
   |                            ---------- move occurs because `account_id` has type `AccountId`, which does not implement the `Copy` trait
...
80 |         self.tokens.insert(account_id, token);
   |                            ---------- value moved here
81 |         self.token_owners.insert(account_id);
   |                                  ^^^^^^^^^^ value used here after move
   |
help: consider cloning the value if the performance cost is acceptable
   |
80 |         self.tokens.insert(account_id.clone(), token);
   |                                      ++++++++

warning: variable does not need to be mutable
   --> src/lib.rs:103:13
    |
103 |         let mut proposal = Proposal {
    |             ----^^^^^^^^
    |             |
    |             help: remove this `mut`
    |
    = note: `#[warn(unused_mut)]` on by default

contarct code →

use near_sdk::borsh::{self, BorshDeserialize, BorshSerialize};
use near_sdk::store::{LookupMap, UnorderedMap, UnorderedSet};
use near_sdk::serde::{Deserialize, Serialize};
use near_sdk::{env, near_bindgen, require, AccountId, BorshStorageKey, PanicOnDefault, NearToken};

#[derive(BorshStorageKey, BorshSerialize)]
enum StorageKey {
    Tokens,
    TokenOwners,
    Proposals,
    ProposalVoters { proposal_id: u64 },
}

#[near_bindgen]
#[derive(BorshDeserialize, BorshSerialize, PanicOnDefault)]
pub struct Contract {
    tokens: LookupMap<AccountId, Token>,
    token_owners: UnorderedSet<AccountId>,
    proposals: UnorderedMap<u64, Proposal>,
    next_proposal_id: u64,
}

#[derive(BorshDeserialize, BorshSerialize, Serialize, Deserialize, Clone)]
#[serde(crate = "near_sdk::serde")]
pub struct Token {
    owner_id: AccountId,
    metadata: TokenMetadata,
}

#[derive(BorshDeserialize, BorshSerialize, Serialize, Deserialize, Clone)]
#[serde(crate = "near_sdk::serde")]
pub struct TokenMetadata {
    title: Option<String>,
    description: Option<String>,
    governance_role: String,
}

#[derive(BorshDeserialize, BorshSerialize, Serialize, Deserialize, Clone)]
#[serde(crate = "near_sdk::serde")]
pub struct Proposal {
    id: u64,
    title: String,
    description: String,
    proposer: AccountId,
    votes_for: NearToken,
    votes_against: NearToken,
    #[serde(skip)]
    voters: UnorderedSet<AccountId>,
    status: ProposalStatus,
}

#[derive(BorshDeserialize, BorshSerialize, Serialize, Deserialize, PartialEq, Clone)]
#[serde(crate = "near_sdk::serde")]
pub enum ProposalStatus {
    Active,
    Passed,
    Rejected,
}

#[near_bindgen]
impl Contract {
    #[init]
    pub fn new() -> Self {
        Self {
            tokens: LookupMap::new(StorageKey::Tokens),
            token_owners: UnorderedSet::new(StorageKey::TokenOwners),
            proposals: UnorderedMap::new(StorageKey::Proposals),
            next_proposal_id: 0,
        }
    }

    pub fn mint(&mut self, account_id: AccountId, metadata: TokenMetadata) {
        require!(!self.tokens.contains_key(&account_id), "Token already exists for this account");
        
        let token = Token {
            owner_id: account_id.clone(),
            metadata,
        };
        
        self.tokens.insert(account_id, token);
        self.token_owners.insert(account_id);
    }

    pub fn token_metadata(&self, account_id: AccountId) -> Option<TokenMetadata> {
        self.tokens.get(account_id).map(|token| token.metadata.clone())
    }

    pub fn is_token_owner(&self, account_id: AccountId) -> bool {
        self.token_owners.contains(&account_id)
    }

    pub fn governance_role(&self, account_id: AccountId) -> Option<String> {
        self.tokens.get(&account_id).map(|token| token.metadata.governance_role.clone())
    }

    pub fn create_proposal(&mut self, title: String, description: String) -> u64 {
        let account_id = env::predecessor_account_id();
        require!(self.is_token_owner(account_id.clone()), "Only holders can create proposals");
        
        let proposal_id = self.next_proposal_id;
        self.next_proposal_id += 1;

        let mut proposal = Proposal {
            id: proposal_id,
            title,
            description,
            proposer: account_id,
            votes_for: NearToken::from_near(0),
            votes_against: NearToken::from_near(0),
            voters: UnorderedSet::new(StorageKey::ProposalVoters { proposal_id }),
            status: ProposalStatus::Active,
        };

        self.proposals.insert(proposal_id, proposal);

        proposal_id
    }

    pub fn vote(&mut self, proposal_id: u64, vote: bool) {
        let account_id = env::predecessor_account_id();
        require!(self.is_token_owner(account_id.clone()), "Only holders can vote");
        
        let mut proposal = self.proposals.get(&proposal_id).expect("Proposal not found");
        require!(proposal.status == ProposalStatus::Active, "Proposal is not active");
        require!(!proposal.voters.contains(&account_id), "Account has already voted");

        if vote {
            proposal.votes_for = proposal.votes_for.saturating_add(NearToken::from_near(1));
        } else {
            proposal.votes_against = proposal.votes_against.saturating_add(NearToken::from_near(1));
        }

        proposal.voters.insert(account_id);

        let total_votes = proposal.votes_for.as_near() + proposal.votes_against.as_near();
        if total_votes >= (self.token_owners.len() / 2 + 1) as u128 {
            if proposal.votes_for > proposal.votes_against {
                proposal.status = ProposalStatus::Passed;
            } else {
                proposal.status = ProposalStatus::Rejected;
            }
        }

        self.proposals.insert(proposal_id, &proposal);
    }

    pub fn get_proposal(&self, proposal_id: u64) -> Option<Proposal> {
        self.proposals.get(&proposal_id)
    }

    pub fn get_all_proposals(&self) -> Vec<Proposal> {
        self.proposals.values().collect()
    }

    pub fn transfer(&mut self, _from: AccountId, _to: AccountId) {
        //the transfer function
    }
}

Any tips on resolving these errors?

Hi, to better assist you could you please share a minimum reproducable example with one error at a time.

A few of the errors it seems from a brief look can be resolved by looking further into the errors for example you are providing the wrong types to funcitons and the value has been used meaning you need to clone or implement copy.

If you haven’t already I would suggesting using the rust analyzer extension for VS code, it will help you spot many of these errors before compile time.

Unless you have a specific reason as not to, you should use the most recent form of the sdk and use the macros it provides such as #[near(contract_state)], take a look at these beautiful macros Release near-sdk-v5.1.0 · near/near-sdk-rs · GitHub

We don’t particularly monitor this board so feel free to reach out here Telegram: Contact @neardev for a quicker response

Sure, will reach out on neardev channel on telegram

Thanking you