ERC-20 is one of the most widely adopted token standards on the Ethereum blockchain. Designed to represent fungible digital assets, ERC-20 tokens are interchangeable—each token holds equal value and functionality, making them ideal for use cases like cryptocurrencies, staking mechanisms, governance voting rights, and in-game currencies. This guide walks you through building a secure and standards-compliant ERC-20 token using OpenZeppelin Contracts, a trusted library for smart contract development.
Whether you're launching a utility token or experimenting with decentralized finance (DeFi) applications, understanding the core mechanics of ERC-20 tokens is essential. We'll explore how to create a custom token, manage supply, handle decimal precision, and ensure compatibility across wallets and exchanges.
👉 Discover how to deploy your first ERC-20 token securely and efficiently.
Building an ERC-20 Token Using OpenZeppelin
Creating an ERC-20 token has never been easier thanks to modular smart contract libraries like OpenZeppelin. By leveraging inheritance, developers can extend pre-audited, battle-tested contracts instead of writing code from scratch—reducing the risk of vulnerabilities.
Let’s build a simple ERC-20 token called Gold (GLD), representing an in-game currency. The implementation uses Solidity and inherits from OpenZeppelin’s ERC20 base contract.
// contracts/GLDToken.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract GLDToken is ERC20 {
constructor(uint256 initialSupply) ERC20("Gold", "GLD") {
_mint(msg.sender, initialSupply);
}
}This minimal yet powerful contract does several important things:
- It imports OpenZeppelin’s
ERC20implementation, which includes all required functions such astransfer,balanceOf, andtotalSupply. - It sets the token name (
Gold) and symbol (GLD) during construction. - It mints an
initialSupplyof tokens to the deployer’s address using the_mintfunction—a secure internal method provided by OpenZeppelin.
Once deployed, this contract allows users to check balances and transfer tokens seamlessly.
For example:
> GLDToken.balanceOf(deployerAddress)
1000000000000000000000Transferring tokens:
> GLDToken.transfer(otherAddress, 300000000000000000000)
> GLDToken.balanceOf(otherAddress)
300000000000000000000The balance updates accordingly for both sender and recipient, demonstrating basic fungibility and transfer functionality.
Understanding Token Decimals and Precision
One of the most misunderstood aspects of ERC-20 tokens is the decimals field. Since the Ethereum Virtual Machine (EVM) only supports integer arithmetic, fractional amounts must be simulated using whole numbers scaled by a power of ten.
The decimals parameter defines how many digits come after the decimal point when displaying token amounts. For instance, if a token uses 18 decimals (the default in OpenZeppelin), then:
1 GLD=1,000,000,000,000,000,000base units (1 × 10¹⁸)1.5 GLD=1,500,000,000,000,000,000base units
Internally, all balances and transfers use these base units—there are no floating-point numbers in Solidity.
👉 Learn how real-world tokens manage decimal precision for seamless user experience.
How Decimals Work in Practice
While decimals affects display logic only, it's crucial for user experience. Wallets, exchanges, and dApps rely on this value to format balances correctly. However, when calling contract functions like transfer, you must pass the amount in base units.
Example: Sending 5 tokens with 18 decimals
transfer(recipient, 5 * (10 ** 18));If you want to customize the number of decimals—for example, to match traditional financial systems with two decimal places—you can override the decimals() function:
function decimals() public view virtual override returns (uint8) {
return 16; // Custom precision
}⚠️ Important: Changing decimals affects how wallets interpret your token. Most DeFi platforms expect 18 decimals by default. Altering this value may lead to display issues or incorrect balance calculations unless properly documented.
Unless you have a specific use case requiring different precision (e.g., stablecoins with 6 or 8 decimals like USDC or DAI), stick with 18 decimals for maximum compatibility.
Core Keywords in ERC-20 Development
To align with search intent and enhance discoverability, here are the core keywords naturally integrated throughout this guide:
- ERC-20 token
- OpenZeppelin Contracts
- Solidity smart contracts
- Fungible tokens
- Token decimals
- Blockchain development
- Smart contract security
- Ethereum token standard
These terms reflect common queries from developers exploring token creation, ensuring this content ranks well for technical audiences seeking reliable implementation guidance.
Frequently Asked Questions (FAQ)
Q: What is an ERC-20 token?
A: An ERC-20 token is a standardized type of fungible token on the Ethereum blockchain. It defines a common set of rules for token behavior, including how tokens are transferred, how balances are queried, and how total supply is accessed.
Q: Why should I use OpenZeppelin to create my token?
A: OpenZeppelin provides secure, modular, and well-documented smart contract components. Their ERC-20 implementation has been audited and widely used across thousands of projects, reducing the risk of bugs or security flaws.
Q: Can I change the total supply after deployment?
A: In the basic ERC20 contract from OpenZeppelin, the total supply is fixed at deployment unless you include extensions like ERC20Capped or ERC20Burnable. If you need dynamic supply management, consider using ERC20PresetMinterPauser.
Q: How do wallets know how many decimals my token has?
A: Wallets and exchanges read the decimals() function from your deployed contract. Always ensure this returns the correct value so balances display accurately.
Q: Is it safe to use _mint() in the constructor?
A: Yes—as long as it's done during initialization and only mints to a trusted address (like the deployer). Avoid exposing public mint functions without access control unless intentional.
Q: Can I rename my token after deployment?
A: No. The name and symbol are immutable once set in the constructor. If changes are needed, you must deploy a new contract.
Final Thoughts on Secure Token Deployment
Building an ERC-20 token with OpenZeppelin streamlines development while promoting best practices in smart contract security. From setting initial supply to handling decimal precision, every decision impacts usability and interoperability.
Before deploying to mainnet, always test your contract on a testnet like Sepolia or use local environments like Hardhat or Foundry. Consider integrating automated testing, formal verification tools, and third-party audits for production-grade deployments.
👉 Get started with secure blockchain development tools today.
By combining OpenZeppelin’s robust foundation with careful design choices—such as using standard decimal values and securing sensitive functions—you can launch a reliable and user-friendly token that integrates smoothly into the broader Web3 ecosystem.