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