How to Issue an ERC20 Token on Ethereum Using Web3J

·

Creating and deploying an ERC20 token on the Ethereum blockchain is a foundational skill for developers entering the world of decentralized applications (dApps) and Web3. With tools like Solidity, Remix IDE, and Web3J, it’s easier than ever to launch your own token—whether for a project, community, or learning purposes. This guide walks you through every step: from writing a compliant ERC20 smart contract to compiling it and deploying it using Java and Web3J.

Understanding the ERC20 Token Standard

The ERC20 standard defines a common set of rules that Ethereum-based tokens must follow, enabling seamless integration across wallets, exchanges, and decentralized platforms. Tokens adhering to this specification can be tracked on explorers like Etherscan and interacted with via standardized interfaces.

Core Functions of ERC20

An ERC20-compliant contract includes several essential functions:

Additionally, two critical events are triggered during transactions:

These functions ensure interoperability and predictability across the Ethereum ecosystem.

👉 Learn how blockchain developers use real-time data to manage tokens.

Writing an ERC20 Token Contract in Solidity

Solidity is the most widely used language for Ethereum smart contracts. It's statically typed and syntactically similar to JavaScript, making it accessible for web developers.

We’ll create a simple token called Steven Ocean Token (SOT) with a fixed supply of 31,415,926 tokens. To get started, we use Remix IDE, a browser-based development environment maintained by the Ethereum Foundation.

🔧 You can access Remix at remix.ethereum.org — no setup required.

Here’s a simplified version of the SOT contract:

pragma solidity 0.4.21;

contract Token {
    uint256 public totalSupply;
    function balanceOf(address _owner) public constant returns (uint256 balance);
    function transfer(address _to, uint256 _value) public returns (bool success);
    function transferFrom(address _from, address _to, uint256 _value) public returns (bool success);
    function approve(address _spender, uint256 _value) public returns (bool success);
    function allowance(address _owner, address _spender) public constant returns (uint256 remaining);

    event Transfer(address indexed _from, address indexed _to, uint256 _value);
    event Approval(address indexed _owner, address indexed _spender, uint256 _value);
}

contract StandardToken is Token {
    mapping (address => uint256) balances;
    mapping (address => mapping (address => uint256)) allowed;

    function transfer(address _to, uint256 _value) public returns (bool success) {
        if (balances[msg.sender] >= _value && _value > 0) {
            balances[msg.sender] -= _value;
            balances[_to] += _value;
            emit Transfer(msg.sender, _to, _value);
            return true;
        }
        return false;
    }

    function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
        if (balances[_from] >= _value && allowed[_from][msg.sender] >= _value && _value > 0) {
            balances[_to] += _value;
            balances[_from] -= _value;
            allowed[_from][msg.sender] -= _value;
            emit Transfer(_from, _to, _value);
            return true;
        }
        return false;
    }

    function balanceOf(address _owner) public constant returns (uint256 balance) {
        return balances[_owner];
    }

    function approve(address _spender, uint256 _value) public returns (bool success) {
        allowed[msg.sender][_spender] = _value;
        emit Approval(msg.sender, _spender, _value);
        return true;
    }

    function allowance(address _owner, address _spender) public constant returns (uint256 remaining) {
        return allowed[_owner][_spender];
    }
}

contract SOT is StandardToken {
    string public constant name = "Steven Ocean Token";
    string public constant symbol = "SOT";
    uint256 public constant decimals = 18;
    uint256 public constant total = 31415926 * 10**decimals;

    function SOT() public {
        totalSupply = total;
        balances[msg.sender] = total;
    }

    function () public payable {
        revert();
    }
}

This contract inherits from StandardToken, implementing core ERC20 logic using two key mappings:

Compiling the Contract and Generating Java Wrappers

To interact with the contract from a Java application, we need to generate Java bindings using Web3J. This requires two files:

You can generate these using the Solidity compiler (solc) or directly from Remix IDE under the "Compile" tab.

Once you have SOT.bin and SOT.abi, run:

web3j solidity generate --javaTypes SOT.bin SOT.abi -o ./src/main/java -p io.github.stevenocean.contracts

This generates a Java class SOT.java extending Web3J’s Contract, providing type-safe methods like:

You can now integrate this into any Java project using Maven or Gradle.

👉 See how developers automate smart contract interactions with APIs.

Deploying Your Token Using Web3J

Before deployment, you’ll need:

  1. An Ethereum wallet with credentials.
  2. Test ETH for gas fees on the Rinkeby testnet.

Step 1: Create a Wallet

Use Web3J to generate a new wallet file:

WalletUtils.generateLightNewWalletFile("password", new File("/path/to/keystore"));

Step 2: Get Test Ether

Visit the Rinkeby Faucet and post your wallet address on Twitter, Facebook, or Google+ to receive test ETH.

Step 3: Connect to Rinkeby Network

Web3j web3 = Web3jFactory.build(new HttpService("https://rinkeby.infura.io/v3/YOUR_PROJECT_ID"));
Credentials credentials = WalletUtils.loadCredentials("password", "/path/to/keystore/your-keyfile");

Step 4: Deploy the Contract

SOT contract = SOT.deploy(web3, credentials, ManagedTransaction.GAS_PRICE, Contract.GAS_LIMIT).send();
String contractAddress = contract.getContractAddress();

After deployment, verify the contract on Rinkeby Etherscan. You’ll see:

Transferring Tokens to Another Address

As the token issuer, you can now send tokens to others. Here’s how to transfer 128 SOT (in wei: 128 * 10^18) to a friend:

Function function = new Function(
    "transfer",
    Arrays.asList(new Address(friendAddress), new Uint256(new BigInteger("128000000000000000000"))),
    Collections.emptyList()
);

String encodedFunction = FunctionEncoder.encode(function);
RawTransactionManager txManager = new RawTransactionManager(web3, credentials);

EthSendTransaction response = txManager.sendTransaction(
    ManagedTransaction.GAS_PRICE,
    Contract.GAS_LIMIT,
    contractAddress,
    encodedFunction,
    BigInteger.ZERO
);

String txHash = response.getTransactionHash();

Once confirmed, the transaction appears on Etherscan with:

You can monitor token balances and transaction history under the Token Holders section on Etherscan.

👉 Discover tools that help track live token movements and blockchain activity.

Frequently Asked Questions (FAQ)

What is an ERC20 token?

ERC20 is a technical standard for fungible tokens on Ethereum. It defines a common interface so that wallets and exchanges can support any token built with it.

Can I deploy an ERC20 token without coding?

Yes! Several no-code platforms allow you to mint tokens quickly. However, understanding Solidity gives you full control over features like minting caps or pausing transfers.

Why use Web3J instead of web3.js?

Web3J enables Java-based backend systems to interact with Ethereum—ideal for enterprise applications where JVM languages dominate.

Is it expensive to deploy a token?

On mainnet, gas costs vary with network congestion. On testnets like Rinkeby (now deprecated but historically used), deployment is free with test ETH.

How do I make my token tradable?

List it on decentralized exchanges like Uniswap by providing liquidity. Centralized exchanges require formal applications.

Can I update my token after deployment?

No—Ethereum smart contracts are immutable. Any changes require deploying a new contract and migrating users.


Core Keywords: ERC20 token, Ethereum blockchain, Solidity smart contract, Web3J Java integration, token deployment, blockchain development, decentralized applications