# 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)