Loading...
Hii, in this smartbook we are going to discuss how to build a complete DApp that deploys ERC20 tokens. We will build a complete interface with plain vanilla JS and nodejs.
The screenshot of application which will look like this :
First we need a proper ERC20 token smart contract. If you have it fine otherwise you can follow the this one :
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
interface IERC20 {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function allowance(address owner, address spender) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
contract ERC20Basic is IERC20 {
string name_;
string symbol_;
uint8 decimals_;
mapping(address => uint256) balances;
mapping(address => mapping (address => uint256)) allowed;
uint256 totalSupply_;
using SafeMath for uint256;
constructor(uint256 total, string memory name, string memory symbol, uint8 decimals) public {
totalSupply_ = total;
name_ = name;
symbol_ = symbol;
decimals_ = decimals;
balances[msg.sender] = totalSupply_;
}
function name() public override view returns (string memory) {
return name_;
}
function symbol() public override view returns (string memory) {
return symbol_;
}
function decimals() public override view returns (uint8) {
return decimals_;
}
function totalSupply() public override view returns (uint256) {
return totalSupply_;
}
function balanceOf(address tokenOwner) public override view returns (uint256) {
return balances[tokenOwner];
}
function transfer(address receiver, uint256 numTokens) public override returns (bool) {
require(numTokens <= balances[msg.sender]);
balances[msg.sender] = balances[msg.sender].sub(numTokens);
balances[receiver] = balances[receiver].add(numTokens);
emit Transfer(msg.sender, receiver, numTokens);
return true;
}
function approve(address delegate, uint256 numTokens) public override returns (bool) {
allowed[msg.sender][delegate] = numTokens;
emit Approval(msg.sender, delegate, numTokens);
return true;
}
function allowance(address owner, address delegate) public override view returns (uint) {
return allowed[owner][delegate];
}
function transferFrom(address owner, address buyer, uint256 numTokens) public override returns (bool) {
require(numTokens <= balances[owner]);
require(numTokens <= allowed[owner][msg.sender]);
balances[owner] = balances[owner].sub(numTokens);
allowed[owner][msg.sender] = allowed[owner][msg.sender].sub(numTokens);
balances[buyer] = balances[buyer].add(numTokens);
emit Transfer(owner, buyer, numTokens);
return true;
}
}
library SafeMath {
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
assert(b <= a);
return a - b;
}
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
assert(c >= a);
return c;
}
}
You can also download a complete file from here :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ERC20 Token Deployer</title>
</head>
<body>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-KyZXEAg3QhqLMpG8r+8fhAXLRk2vvoC2f3B09zVXn8CA5QIVfZOJ3BCsw2P0p/We" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/js/bootstrap.bundle.min.js"
integrity="sha384-U1DAWAznBHeqEIlVSCgzq+c9gqGAJn5c/t99JyeKa9xxaYpSvHU5awsuZVVFIhvj"
crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/web3/3.0.0-rc.5/web3.min.js"
integrity="sha512-jRzb6jM5wynT5UHyMW2+SD+yLsYPEU5uftImpzOcVTdu1J7VsynVmiuFTsitsoL5PJVQi+OtWbrpWq/I+kkF4Q=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"
integrity="sha512-894YE6QWD5I59HgZOGReFYm4dnWc1Qt5NtvYSaNcOP+u1T9qYdvdihz0PPSiiqn/+/3e7Jo4EaG7TubfWGUrMQ=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<nav class="navbar navbar-expand-lg navbar-light bg-light shadow-sm">
<div class="container">
<a class="navbar-brand fw-bolder text-primary" href="#">ERC20 Token Ganerator</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse"
data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false"
aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<span class="ms-auto me-2">
<span class="navbar-text d-none" id="accountaddress"></span>
<button class="btn btn-outline-primary" id="loginbutton"><i
class="fas fa-sign-in-alt pe-1"></i>LogIN</button>
</span>
</div>
</div>
</nav>
<div class="row justify-content-center">
<div class="col-sm-8 col-lg-6 col-xl-4 border border-5 rounded shadow mt-5 p-5">
<h3 class="fw-bolder text-center my-3">ERC20 Tokens Generator</h3>
<hr>
<div class="mt-5 mb-3">
<label for="exampleFormControlInput1" class="form-label fw-bold text-primary">Token Name:</label>
<input type="email" class="form-control" id="tokenname" placeholder="EtherLite">
</div>
<div class="mb-3">
<label for="exampleFormControlTextarea1" class="form-label fw-bold text-primary">Token Symbol:</label>
<input class="form-control" id="tokensymbol" rows="3" placeholder="ETL">
</div>
<div class="mb-3">
<label for="exampleFormControlinput1" class="form-label fw-bold text-primary">TotalSupply:</label>
<input class="form-control" id="tokensupply" rows="3" placeholder="35000000000000000000000000000">
</div>
<div class="mb-3">
<label for="exampleFormControlinput1" class="form-label fw-bold text-primary">Decimals:</label>
<input class="form-control" id="tokendecimals" rows="3" placeholder="18">
</div>
<div class="d-grid gap-2">
<button class="btn btn-primary mt-3 shadow" type="button" id="createtoken">Create Token</button>
</div>
</div>
<p id="contractreceipt"></p>
</div>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css"
integrity="sha512-1ycn6IcaQQ40/MKBW2W4Rhis/DbILU74C1vSrLJxCq57o941Ym01SwNsOMqvEBFlcgUa6xLiPY/NS5R+E6ztJQ=="
crossorigin="anonymous" referrerpolicy="no-referrer" />
<script src="//cdn.jsdelivr.net/npm/sweetalert2@11"></script>
</body>
</html>
var web3, account = '0x00';
var response;
var abi, bytecode;
async function CheckMetamaskConnection() {
if (window.ethereum) {
gotaddress = false;
web3 = new Web3(window.ethereum);
await ethereum.enable();
await ethereum.request({
method: 'eth_accounts',
}).then(async (result) => {
account = result[0]
console.log(account)
gotaddress = true
});
if (gotaddress) {
var chainID = await ethereum.request({
method: 'eth_chainId'
});
console.log("network is", chainID);
if (chainID == 3) {
return true;
} else {
return false;
};
}
}
else if (window.web3) {
window.web3 = new Web3(web3.currentProvider);
return true
}
else {
console.log('Non-Ethereum browser detected. You should consider trying MetaMask!');
return false;
}
}
var loginbutton = document.getElementById('loginbutton');
loginbutton.onclick = async function () {
var isMetamask = await CheckMetamaskConnection();
if (!isMetamask) {
Swal.fire({
icon: 'info',
title: 'Metamask not detected !',
text: 'Make sure you have installed metamask and on Etherlite network !',
footer: '<a href="https://doc.etherlite.org/for-developers/wallets">How to Add EtherLite Network in Metamask?</a>'
})
} else {
ethereum.on('accountsChanged', function (accounts) {
Swal.fire({
icon: 'success',
title: 'Metamask account connected!',
timer: 3000,
showConfirmButton: false,
})
account = accounts[0];
if (account == undefined) {
loginbutton.classList.remove('d-none');
document.getElementById('accountaddress').classList.add('d-none');
} else {
document.getElementById('accountaddress').innerText = account;
}
});
document.getElementById('accountaddress').innerText = account;
loginbutton.classList.add("d-none");
document.getElementById('accountaddress').classList.remove('d-none');
}
}
var createtokenbutton = document.getElementById('createtoken');
createtokenbutton.onclick = async function () {
Swal.fire({
title: "Deploying Contract...",
allowOutsideClick: false,
didOpen: () => {
Swal.showLoading()
},
}).then(result => { });
if (account == '0x00') {
Swal.fire({
icon: 'info',
title: 'LogIn first !',
text: 'connect Metamask and login!',
})
} else {
console.log("creating tokens");
var tokenname = document.getElementById('tokenname').value;
var tokensymbol = document.getElementById('tokensymbol').value;
var tokensupply = document.getElementById('tokensupply').value;
var tokendecimals = document.getElementById('tokendecimals').value;
await $.ajax({
url: '/compile',
complete: function (data) {
console.log(data);
response = data.responseJSON
},
}).then(function () {
if (response.message == "error") {
Swal.fire({
icon: 'error',
title: 'Error!',
text: 'Contract compile failed!',
})
} else {
bytecode = response.evm.bytecode.object;
abi = response.abi;
console.log(abi);
deploy(tokensupply, tokenname, tokensymbol, tokendecimals);
}
});
}
}
async function deploy(supply, name, symbol, decimals) {
console.log(abi)
const contract = new web3.eth.Contract(abi);
console.log(contract)
const contractTX = contract.deploy({
data: bytecode,
arguments: [supply, name, symbol, decimals],
})
console.log(contractTX)
web3.eth.sendTransaction({
from: account,
data: contractTX.encodeABI(), // deploying a contract
}).then((receipt) => {
console.log(receipt);
Swal.fire({
icon: 'success',
title: 'ERC20 Tokens created!',
timer: 3000,
showConfirmButton: false,
})
document.getElementById('contractreceipt').innerHTML = `<span class="fw-bold">Contract Address : </span> <br> ${receipt.contractAddress}<br><br><a href="https://ropsten.etherscan.io/address/${receipt.contractAddress}">View Transaction on etherscan</a>`;
})
};
{
"name": "token_deployer",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"express": "^4.17.1",
"solc": "^0.8.6",
"web3": "^1.5.0"
}
}
var express = require('express')
var path = require('path')
const fs = require('fs');
const solc = require('solc');
var app = express()
var port = process.env.PORT || 3000
app.use(express.static(path.join(__dirname, './public')));
app.get('/', function (req, res) {
res.sendFile(__dirname + '/index.html')
});
app.get('/compile', function (req, res) {
const contractPath = path.resolve(__dirname, 'public/contract/ERC20Basic.sol');
const source = fs.readFileSync(contractPath, 'utf8');
const input = {
language: 'Solidity',
sources: {
'ERC20Basic.sol': {
content: source,
},
},
settings: {
outputSelection: {
'*': {
'*': ['*'],
},
},
},
};
const tempFile = JSON.parse(solc.compile(JSON.stringify(input)));
if (tempFile.errors) {
console.log("goterror");
res.send({ message: 'error' });
} else {
console.log("everything is fine")
const contractFile = tempFile.contracts['ERC20Basic.sol']['ERC20Basic'];
res.send(contractFile);
}
})
app.listen(port, function () {
console.log('Listening on port ' + port)
})
Get the complete DApp here :