---
# System prepended metadata

title: Writing Voting Smart Contract On NEAR Using Rust

---

# Writing Voting Smart Contract On NEAR Using Rust

In this tutorial we will write a very basic and simple smart contract using Rust language and `near-sdk-rs` then deploy it to `NEAR testnet`.

1- Clone The Smart Contract Template Repository
```shell
$ git clone git@github.com:near-examples/rust-template.git voting_contract
$ cd voting_contract
```
2- Open the cloned repository in your editor or VSCode using:
```shell
$ code .
```
3- Change the project name in the `Cargo.toml` file
```toml
[package]
name = "vote_contract"
version = "0.1.0"
```
4- Writing the contract state

we will change the struct name to `VotingContract` and add 2 private state variables to it.

**candidates**: for storing candidate names with their total votes.

**voters**: for storing voters account ids with the voted candidate name.

``` rust
#[near_bindgen]
#[derive(BorshDeserialize, BorshSerialize)]
pub struct VoteContract {
    // SETUP CONTRACT STATE
    candidates: UnorderedMap<String,i128>,
    voters: UnorderedMap<String,String>
}
```

5- Add default implementation to initalize the state variables

```rust
impl Default for VoteContract {
    fn default() -> Self {
        Self {
            candidates: UnorderedMap::new(b"a"),
            voters: UnorderedMap::new(b"b")
        }
    }
}
```

6- Write the methods implementations for this contract

```rust
#[near_bindgen]
impl VoteContract {
    // ADD CONTRACT METHODS HERE
    pub fn add_candidate(&mut self, name: String) -> String{
        
        if !self.candidates.get(&name).is_none(){
            return "Candidate already in the list.".to_string();
        }

        self.candidates.insert(&name,&0);
        
        return ["Candidate",&name,"Added."].join(" ");
    }

    pub fn get_candidates(&self) -> Vec<String>{
        return self.candidates.keys_as_vector().to_vec().clone();
    }

    pub fn show_results(&self) -> Vec<(String,i128)>{

        if self.voters.get(&env::signer_account_id().to_string()).is_none() {
            return [("You must vote first to show the results.".to_string(),0)].to_vec();
        }

        return self.candidates.iter().map(|x|x).collect();
    }

    pub fn show_voters(&self) -> Vec<(String,String)>{

        if self.voters.get(&env::signer_account_id().to_string()).is_none() {
            return [("You must vote first to show the voters.".to_string(),"".to_string())].to_vec();
        }

        return self.voters.iter().map(|x|x).collect();
    }

    pub fn add_vote(&mut self, name: String) -> String{
        
        if self.candidates.get(&name).is_none(){
            return "Candidate not found!".to_string();
        }

        if !self.voters.get(&env::signer_account_id().to_string()).is_none() {
            return "You already voted before!".to_string();
        }

        let mut val = self.candidates.get(&name).unwrap();
        val += 1;

        self.candidates.insert(&name,&val);

        self.voters.insert(&env::signer_account_id().to_string(), &name);
            
        return ["You voted for",&name,"successfully.","Total votes:", &val.to_string()].join(" ");
    }
}

```
7- Build the project
```shell
$ ./build.sh
```
it will create the executable `.wasm` file in `./res` folder.

8- Login with NEAR testnet account
```shell
$ npm install -g near-cli # if not installed
$ near login
$ export ID={YOUR_LOGGED_IN_ACCOUNT_ID}
```
9- Create Sub-Account to deploy the contract on it

```shell
$ near create-account vote.$ID --masterAccount $ID --initialBalance 1
```
10- Deploy the contract to the sub-account
```shell
$ near deploy --wasmFile ./res/vote_contract.wasm --accountId vote.$ID
```
11- Calling the contract functions
```shell
$ near call vote.$ID add_candidate '{"name":"Eslam"}' --accountId $ID
# Result: 'Candidate Eslam Added.'
$ near call vote.$ID add_candidate '{"name":"Malek"}' --accountId $ID
# Result: 'Candidate Malek Added.'
$ near call vote.$ID get_candidates '' --accountId $ID
# Result: [ 'Eslam', 'Malek' ]
$ near call vote.$ID add_vote '{"name":"Malek"}' --accountId $ID
# Result: 'You voted for Malek successfully. Total votes: 1'
$ near call vote.$ID show_results '' --accountId $ID
# Result: [ [ 'Eslam', 0 ], [ 'Malek', 1 ] ]
$ near call vote.$ID show_voters '' --accountId $ID
# Result: [ [ 'eslamx7.testnet', 'Malek' ] ]
```

That's it.
Happy Coding!


------
> If you think this is useful, Please Consider Donation: [eslamx7.near](https://wallet.near.org/send-money)