How to Develop a Simple DApp on Ethereum

·

Building decentralized applications (DApps) on the Ethereum blockchain opens the door to trustless, transparent, and secure digital interactions. In this guide, we’ll walk through creating a simple voting DApp — a practical example that demonstrates core concepts of Ethereum development, from writing smart contracts in Solidity to deploying and interacting with them via a web interface.

Whether you're new to blockchain or expanding your Web3 development skills, this step-by-step tutorial covers everything you need to build, deploy, and interact with a functional DApp using modern Ethereum tools.


Setting Up the Development Environment

Before diving into coding, ensure your local machine has the necessary tools installed:

Install these tools using your preferred package manager. For example:

npm install -g solc web3 ganache

Once installed, you can launch a local blockchain for testing:

👉 Start building your first DApp with a secure development environment setup


Writing the Smart Contract in Solidity

We'll create a simple voting system where users can vote for candidates and view real-time vote counts. Below is the Voting.sol contract written in Solidity:

pragma solidity ^0.4.11;

contract Voting {
    mapping (bytes32 => uint8) public votesReceived;
    bytes32[] public candidateList;

    function Voting(bytes32[] candidateNames) {
        candidateList = candidateNames;
    }

    function totalVotesFor(bytes32 candidate) returns (uint8) {
        if (!validCandidate(candidate)) revert();
        return votesReceived[candidate];
    }

    function voteForCandidate(bytes32 candidate) {
        if (!validCandidate(candidate)) revert();
        votesReceived[candidate] += 1;
    }

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

Key Features:

Note: While newer versions of Solidity use require() and revert(), this example uses older syntax (throw) for compatibility with legacy tutorials.

Compiling the Contract

Open a Node.js console and run the following commands to compile the contract:

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

solc = require('solc');
code = fs.readFileSync('Voting.sol').toString();
compiledCode = solc.compile(code);

The compiledCode object contains both the ABI (Application Binary Interface) and bytecode needed for deployment.


Deploying the Smart Contract

Deployment connects your compiled contract to the Ethereum network — in this case, your local test chain.

Extract the ABI and bytecode:

abiDefinition = JSON.parse(compiledCode.contracts[':Voting'].interface);
byteCode = compiledCode.contracts[':Voting'].bytecode;

Create a contract instance and deploy it:

VotingContract = web3.eth.contract(abiDefinition);
deployedContract = VotingContract.new(
  ['Rama', 'Nick', 'Jose'],
  { data: byteCode, from: web3.eth.accounts[0], gas: 4700000 }
);

After deployment, retrieve the contract address:

deployedContract.address;
contractInstance = VotingContract.at(deployedContract.address);

This contractInstance allows you to interact with the deployed contract programmatically.


Interacting via Console

Test the contract directly in the Node.js console:

// Check current votes
contractInstance.totalVotesFor.call('Rama');

// Cast votes
contractInstance.voteForCandidate('Rama', { from: web3.eth.accounts[0] });

// Verify updated count
contractInstance.totalVotesFor.call('Rama').toString();

Each transaction simulates real-world behavior — changing state on the blockchain and consuming gas.

👉 Learn how blockchain transactions work under the hood


Building a Web Interface for User Interaction

Now let’s make the DApp accessible through a browser. Create two files: index.html and index.js.

index.html

<!DOCTYPE html>
<html>
<head>
  <title>SSC VOTING APPLICATION</title>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
</head>
<body>
  <h1>SSC VOTING APPLICATION</h1>
  <div id="candidates">
    <table>
      <tr><th>Candidate</th><th>Votes</th></tr>
      <tr><td>Rama</td><td id="candidate-1"></td></tr>
      <tr><td>Nick</td><td id="candidate-2"></td></tr>
      <tr><td>Jose</td><td id="candidate-3"></td></tr>
    </table>
  </div>
  <br/>
  <input type="text" id="candidate" placeholder="Candidate Name" />
  <button onclick="voteForCandidate()">Vote</button>
  <script src="index.js"></script>
</body>
</html>

index.js

web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
abi = JSON.parse('[{"constant":false,"inputs":[{"name":"candidate","type":"bytes32"}],"name":"totalVotesFor","outputs":[{"name":"","type":"uint8"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"candidate","type":"bytes32"}],"name":"validCandidate","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"votesReceived","outputs":[{"name":"","type":"uint8"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"x","type":"bytes32"}],"name":"bytes32ToString","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"candidateList","outputs":[{"name":"","type":"bytes32"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"candidate","type":"bytes32"}],"name":"voteForCandidate","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"contractOwner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"inputs":[{"name":"candidateNames","type":"bytes32[]"}],"payable":false,"type":"constructor"}]');

VotingContract = web3.eth.contract(abi);
contractInstance = VotingContract.at('0x4131a0f92d36932d3ec3b7a0581546f2e662ad0b'); // Replace with your deployed address

candidates = {"Rama": "candidate-1", "Nick": "candidate-2", "Jose": "candidate-3"}

function voteForCandidate() {
  let candidateName = $("#candidate").val();
  contractInstance.voteForCandidate(candidateName, {from: web3.eth.accounts[0]}, function() {
    let div_id = candidates[candidateName];
    $("#" + div_id).html(contractInstance.totalVotesFor.call(candidateName).toString());
  });
}

$(document).ready(function() {
  Object.keys(candidates).forEach(function(name) {
    let val = contractInstance.totalVotesFor.call(name).toString();
    $("#" + candidates[name]).html(val);
  });
});

Replace the contract address with your own after deployment.

Open index.html in a browser (served over HTTP, not file://), connect MetaMask to localhost:8545, and start voting!


Frequently Asked Questions

Q: What is a DApp?
A: A decentralized application (DApp) runs on a blockchain network instead of a central server. It uses smart contracts for logic and provides censorship-resistant functionality.

Q: Why use Ganache instead of the mainnet?
A: Ganache offers a safe, fast, and free environment for testing without risking real funds or paying high gas fees.

Q: Can I use Truffle or Hardhat instead?
A: Yes! Tools like Truffle and Hardhat streamline compilation, testing, and deployment. This guide uses raw tools to clarify underlying processes.

Q: How do users interact with my DApp?
A: Users connect via wallets like MetaMask, which injects a Web3 provider into the browser, enabling direct interaction with smart contracts.

Q: Is Solidity still relevant?
A: Absolutely. Solidity remains the most widely used language for Ethereum smart contracts, supported by extensive tooling and community resources.

Q: Can I upgrade this voting DApp for production?
A: Yes — add features like voter registration, vote delegation, or integration with identity systems (e.g., ENS). Also consider security audits and gas optimization.


Core Keywords for SEO

These keywords are naturally integrated throughout the content to enhance search visibility while maintaining readability.


With this foundation, you’re ready to explore more advanced topics like event logging, front-end frameworks (React/Vue), and integrating wallet connectivity. The world of Web3 awaits — start building today.

👉 Explore more Web3 development resources and tools