Jump to content

ether-vote


cwade12c
 Share

Recommended Posts

ether-vote

A decentralized voting application using the Ethereum blockchain architecture.

N|Solid

Features

  • Initialize a collection of candidates who will be applying for a position
  • Votes are stored on the blockchain
  • No central authority is required to trust

Goals

This current version is a proof of concept. Voting systems can serve as a building block for many complex decentralized applications. In the future, the following goals will be completed:

  • Rebuild the app using the Truffle framework
  • Provide clear instructions for deploying the dapp to a testnet
  • Add the ability to interact with the smart contract from the command line
  • Implement a voting token (with a limited supply) into the smart contract
  • Implement a payment system into the dapp that would allow users to buy/sell voting tokens

Code

EtherVote.sol

pragma solidity ^0.4.11;

contract EtherVote {
	mapping (bytes32 => uint8) public numberOfVotesReceived;
	bytes32[] public listOfCandidates;

	function EtherVote(bytes32[] candidates) {
		listOfCandidates = candidates;
	}

	function isValidCandidate(bytes32 candidate) returns (bool) {
		for(uint index = 0; index < listOfCandidates.length; index++) {
			if(listOfCandidates[index] == candidate) {
				return true;
			}
		}
		return false;
	}

	function getTotalVotesForCandidate(bytes32 candidate) returns (uint8) {
		require(isValidCandidate(candidate));
		return numberOfVotesReceived[candidate];
	}

	function setVoteForCandidate(bytes32 candidate) {
		require(isValidCandidate(candidate));
		numberOfVotesReceived[candidate] += 1;
	}
}

 

.bowerrc

{
    "directory": "web/vendor/"
}

 

bower.json

{
  "name": "ether-vote",
  "appPath": "web",
  "version": "0.0.1",
  "dependencies": {
    "lodash": "~4.17.4",
    "bootstrap": "v4.0.0-alpha.6",
    "less": "~2.7.2"
  }
}

 

package.json

{
  "name": "ether-vote",
  "version": "0.0.1",
  "devDependencies": {
    "ethereumjs-testrpc": "^4.1.1",
    "web3": "^0.20.1",
    "solc": "^0.4.16"
  }
}

 

Usage (Node)

To retrieve the number of votes for a given candidate:

contractInstance.getTotalVotesForCandidate.call('Holo');

To cast a vote for a particular candidate:

contractInstance.setVoteForCandidate('Kurisu', {from: web3.eth.accounts[1]});

Installation

ether-vote requires Node.js and bower to run.

Step 1 - Install the frontend dependencies:

bower install

Step 2 - Install the node modules:

npm install

Step 3 - Run testrpc

node_modules/.bin/testrpc

This will generate 10 keypairs (public addresses / private keys) that each have 100 Ether for testing purposes. For example:

EthereumJS TestRPC v4.1.1 (ganache-core: 1.1.2)

Available Accounts
==================
(0) 0x3853246f7dd692044b01786ea42a88197f6dfef9
(1) 0x1067092bee809c703ed33c11cc2ca3f3d3e33f1f
(2) 0x4b9ad5d76fc3abe51d02fa9c631fe2e6dd21261a
(3) 0xbe5dacc37242be5ca41baa25a88657e73fbae2c1
(4) 0x8afc23d930072c286c31a22d6ec5cb9330acd51e
(5) 0x21deb9442d2ac8aefdeaf4521e568a98de3ebb6f
(6) 0x39c9c3fffaff694388354aa40d22236ff102cb01
(7) 0x6927e56ae99f8a9531eaa5769486f0d9c67f1d07
(8) 0x65ad95852c58d7a9ab6177a55aa50f4c98507a83
(9) 0xb963574b692ace8f3f392531ba46788258d19eb6

Private Keys
==================
(0) fb1e07512bfa729237496733dce0ba217356aaa5c14aecf3cecc317042bc77cc
(1) 1b504d05041f1513c14dda6cfcced3b28ae5a47e33a75ce84a5d724adef69f6a
(2) e5756fb44810101d141443a4f20d21dbb7ddfb79157a447721a3fc8a118934bc
(3) bf811c983a80f53ec805bb956720946672a45e6739fe9d34f8099855f3658f17
(4) 681a0a2d42087966db7ca600f92c9b375f87b2e6dfae53e9358dbf54f3e26fc8
(5) b104ed383582580eae090a6d883307245d67d338db9e988312c28a30c61b543a
(6) f74738475aef7b0340f902ea85c0900831b1e1b337bc0f0891e56540eed26491
(7) 96dfa361e52f3f45b24a058846ea6df844f8a89842ef83855309bb0c7827913f
(8) 9cb8adf3b2e5026582b20f0c65aae2c2c4f6adb3e406cd3a52df93050a5b12fe
(9) 4b152799a199aa7200432698d14aa80f970232ee0c97809e45b87880814dad65

HD Wallet
==================
Mnemonic:      drama aspect juice culture foot federal frequent pizza hawk giggle tenant happy
Base HD Path:  m/44'/60'/0'/0/{account_index}

Listening on localhost:8545

Step 4.0 - Run

node

Step 4.1 - Include web3.js

Web3 = require('web3'); 
web3 = new Web3(new Web3.providers.HttpProvider("http://127.0.0.1:8545"));

Step 4.2 - Set the output of EtherVote.sol to a variable

smartContract = fs.readFileSync('EtherVote.sol').toString();

Step 4.3 - Compile the contract using solc

solc = require('solc'); 
compiledCode = solc.compile(smartContract);

The output will return a JSON object that contains important information like the Ethereum Contract Application Binary Interface (ABI) and smart contract bytecode. For example:

{
  contracts: {
    ':EtherVote': {
      assembly: [
        Object
      ],
      bytecode: '6060604052341561000f57600080fd5b6040516103dc3803806103dc833981016040528080518201919050505b806001908051906020019061004292919061004a565b505b506100c2565b82805482825590600052602060002090810192821561008c579160200282015b8281111561008b57825182906000191690559160200191906001019061006a565b5b509050610099919061009d565b5090565b6100bf91905b808211156100bb57600081600............continued............',
      functionHashes: [
        Object
      ],
      gasEstimates: [
        Object
      ],
      interface: '[{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"numberOfVotesReceived","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},............continued............]',
      metadata: '{"compiler":{"version":"0.4.16+commit.d7661dd9"},"language":"Solidity","output":{"abi":[{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"numberOfVotesReceived","outputs":[{"name":"","type":"uint8"}],............continued............}]}',
      opcodes: 'PUSH1 0x60 PUSH1 0x40 MSTORE CALLVALUE ISZERO PUSH2 0xF JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x3DC CODESIZE SUB DUP1 PUSH2 0x3DC DUP4 CODECOPY DUP2 ADD PUSH1 0x40 MSTORE DUP1 DUP1 MLOAD DUP3 ADD SWAP2 SWAP1 POP POP JUMPDEST DUP1 PUSH1 0x1 SWAP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 PUSH2 0x42 SWAP3 SWAP2 SWAP1 PUSH2 0x4A JUMP JUMPDEST POP JUMPDEST POP PUSH2 0xC2 JUMP JUMPDEST DUP3 DUP1 SLOAD DUP3 DUP3 SSTORE SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 ............continued............ ',
      runtimeBytecode: '60606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680630d8de22c1461006a5780633898ac29146100ab5780638c1d9f30146100ec57806392d7df4a1461012b578063dcebb25e1461016a575b600080fd5b34156100............continued............',
      srcmap: '2',
      srcmapRuntime: '',
      sourceList: [
        ''
      ],
      sources: {
        '': {
          AST: [
            Object
          ]
        }
      }
    }
}

 

Step 5.0 - Create an ABI definition object by passing in the ABI definition as JSON from the compiledCode object that was created in Step 4.3. Then, pass this ABI definition object to the web3.eth.contract function in order to create an EtherVote object.

abiDefinition = JSON.parse(compiledCode.contracts[':EtherVote'].interface); 
EtherVoteContract = web3.eth.contract(abiDefinition);

Step 5.1 - Save the byteCode object from the compiledCode object to a variable, as we will use this when calling our EtherVoteContract's prototypical .new() function

byteCode = compiledCode.contracts[':Voting'].bytecode;

Step 5.2 - Deploy the smart contract to the Ethereum blockchain by invoking EtherVoteContract.new(...), which takes in two parameters:

  • The first parameter are the values for the constructor - in this case, our list of candidates to vote for

  • The second parameter is an object that contains the following properties:

    Property Description
    data The compiled bytecode that will be deployed to the Ethereum blockchain
    from The address that will deploy the smart contract
    gas The amount of money that will be offered to miners in order to include the code on the blockchain
deployedContract = EtherVoteContract.new(['Kurisu', 'Holo', 'Rin', 'Haruhi', 'Mitsuha'], { data: byteCode, from: web3.eth.accounts[0], gas: 4700000 } );

Step 5.3 - Create an instance of the smart contract by invoking the at function on the EtherVoteContract object, passing in the address property from the deployedContract object that was created in Step 5.2

contractInstance = EtherVoteContract.at(deployedContract.address);

Congratulations, you are now ready to interact with the dapp! (See: Usage above)

  • I Like This! 2
Link to comment
Share on other sites

I don't have enough practical knowledge of blockchain to fully appreciate this right now. But kudos! I have a more abstract question though: could this be implemented in an app that allows you to vote for local representatives?  A big problem in society today is that people turn out and vote for the president but they frequently don't participate in more local matters.  If there were an app that gave people instant notifications on their phone to vote for issues it could be a real benefit to society!

Link to comment
Share on other sites

  • 5 months later...

I don't have much knowledge on blockchain technology either, but I have heard of some great uses that people are working on outside of cryptocurrency. I've heard about blockchain voting and would definitely like to read more into it. Also the SingularityNET project of AI on blockchain sounds interesting too.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...