To demonstrate the integration of Web3.js with Solidity, we will create a basic voting dApp. This application will allow users to vote on proposals and view the current vote counts. We will cover the following topics:

  1. Setting up the development environment.
  2. Writing the Solidity smart contract.
  3. Interacting with the smart contract using Web3.js.
  4. Deploying the dApp to a local Ethereum network.

Setting Up the Development Environment

Before we begin, ensure you have the following tools installed:

  • Node.js (version 12.x or higher)
  • npm (Node package manager)
  • Truffle framework
  • Ganache (for local Ethereum blockchain)

You can install Truffle globally using npm:

npm install -g truffle

Next, create a new directory for your project and initialize a new Truffle project:

mkdir VotingDApp
cd VotingDApp
truffle init

Install Web3.js in your project:

npm install web3

Writing the Solidity Smart Contract

In the contracts directory, create a new file named Voting.sol. This contract will allow users to propose candidates and vote for them.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract Voting {
    struct Candidate {
        uint id;
        string name;
        uint voteCount;
    }

    mapping(uint => Candidate) public candidates;
    mapping(address => bool) public voters;
    uint public candidatesCount;

    event votedEvent(uint indexed _candidateId);

    constructor() {
        addCandidate("Alice");
        addCandidate("Bob");
    }

    function addCandidate(string memory _name) private {
        candidatesCount++;
        candidates[candidatesCount] = Candidate(candidatesCount, _name, 0);
    }

    function vote(uint _candidateId) public {
        require(!voters[msg.sender], "You have already voted.");
        require(_candidateId > 0 && _candidateId <= candidatesCount, "Invalid candidate ID.");

        voters[msg.sender] = true;
        candidates[_candidateId].voteCount++;

        emit votedEvent(_candidateId);
    }
}

Interacting with the Smart Contract Using Web3.js

Create a new file named app.js in the root directory of your project. This file will contain the front-end logic to interact with the smart contract.

const Web3 = require('web3');
const contractABI = /* ABI from compiled contract */;
const contractAddress = '/* Deployed contract address */';

const web3 = new Web3('http://localhost:7545'); // Ganache default port
const votingContract = new web3.eth.Contract(contractABI, contractAddress);

async function vote(candidateId) {
    const accounts = await web3.eth.getAccounts();
    await votingContract.methods.vote(candidateId).send({ from: accounts[0] });
    console.log(`Voted for candidate ID: ${candidateId}`);
}

async function getCandidates() {
    const candidatesCount = await votingContract.methods.candidatesCount().call();
    for (let i = 1; i <= candidatesCount; i++) {
        const candidate = await votingContract.methods.candidates(i).call();
        console.log(`Candidate: ${candidate.name}, Votes: ${candidate.voteCount}`);
    }
}

getCandidates();
vote(1); // Example: Voting for candidate with ID 1

Deploying the dApp to a Local Ethereum Network

To deploy your smart contract to a local Ethereum network, you will need to create a migration script. In the migrations directory, create a new file named 2_deploy_contracts.js:

const Voting = artifacts.require("Voting");

module.exports = function (deployer) {
    deployer.deploy(Voting);
};

Now, start Ganache and create a new workspace. Then, deploy your contracts using Truffle:

truffle migrate

Summary

In this tutorial, we have covered how to set up a simple voting dApp using Solidity and Web3.js. Below is a summary of the key components:

ComponentDescription
Solidity ContractManages candidates and voting logic
Web3.jsInteracts with the Ethereum blockchain
TruffleFramework for deploying smart contracts
GanacheLocal Ethereum blockchain for testing

Best Practices

  • Error Handling: Always implement error handling when calling smart contract methods.
  • Gas Optimization: Optimize your smart contract code to reduce gas costs.
  • Security Audits: Conduct thorough audits of your smart contracts to avoid vulnerabilities.

Learn more with useful resources