735546619e
Signed-off-by: T-Hax <>
78 lines
4.8 KiB
Plaintext
78 lines
4.8 KiB
Plaintext
= ERC20
|
|
|
|
An ERC20 token contract keeps track of xref:tokens.adoc#different-kinds-of-tokens[_fungible_ tokens]: any one token is exactly equal to any other token; no tokens have special rights or behavior associated with them. This makes ERC20 tokens useful for things like a *medium of exchange currency*, *voting rights*, *staking*, and more.
|
|
|
|
OpenZeppelin Contracts provides many ERC20-related contracts. On the xref:api:token/ERC20.adoc[`API reference`] you'll find detailed information on their properties and usage.
|
|
|
|
[[constructing-an-erc20-token-contract]]
|
|
== Constructing an ERC20 Token Contract
|
|
|
|
Using Contracts, we can easily create our own ERC20 token contract, which will be used to track _Gold_ (GLD), an internal currency in a hypothetical game.
|
|
|
|
Here's what our GLD token might look like.
|
|
|
|
[source,solidity]
|
|
----
|
|
// contracts/GLDToken.sol
|
|
// SPDX-License-Identifier: MIT
|
|
pragma solidity ^0.6.0;
|
|
|
|
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
|
|
|
|
contract GLDToken is ERC20 {
|
|
constructor(uint256 initialSupply) public ERC20("Gold", "GLD") {
|
|
_mint(msg.sender, initialSupply);
|
|
}
|
|
}
|
|
----
|
|
|
|
Our contracts are often used via https://solidity.readthedocs.io/en/latest/contracts.html#inheritance[inheritance], and here we're reusing xref:api:token/ERC20.adoc#erc20[`ERC20`] for both the basic standard implementation and the xref:api:token/ERC20.adoc#ERC20-name--[`name`], xref:api:token/ERC20.adoc#ERC20-symbol--[`symbol`], and xref:api:token/ERC20.adoc#ERC20-decimals--[`decimals`] optional extensions. Additionally, we're creating an `initialSupply` of tokens, which will be assigned to the address that deploys the contract.
|
|
|
|
TIP: For a more complete discussion of ERC20 supply mechanisms, see xref:erc20-supply.adoc[Creating ERC20 Supply].
|
|
|
|
That's it! Once deployed, we will be able to query the deployer's balance:
|
|
|
|
[source,javascript]
|
|
----
|
|
> GLDToken.balanceOf(deployerAddress)
|
|
1000000000000000000000
|
|
----
|
|
|
|
We can also xref:api:token/ERC20.adoc#IERC20-transfer-address-uint256-[transfer] these tokens to other accounts:
|
|
|
|
[source,javascript]
|
|
----
|
|
> GLDToken.transfer(otherAddress, 300000000000000000000)
|
|
> GLDToken.balanceOf(otherAddress)
|
|
300000000000000000000
|
|
> GLDToken.balanceOf(deployerAddress)
|
|
700000000000000000000
|
|
----
|
|
|
|
[[a-note-on-decimals]]
|
|
== A Note on `decimals`
|
|
|
|
Often, you'll want to be able to divide your tokens into arbitrary amounts: say, if you own `5 GLD`, you may want to send `1.5 GLD` to a friend, and keep `3.5 GLD` to yourself. Unfortunately, Solidity and the EVM do not support this behavior: only integer (whole) numbers can be used, which poses an issue. You may send `1` or `2` tokens, but not `1.5`.
|
|
|
|
To work around this, xref:api:token/ERC20.adoc#ERC20[`ERC20`] provides a xref:api:token/ERC20.adoc#ERC20-decimals--[`decimals`] field, which is used to specify how many decimal places a token has. To be able to transfer `1.5 GLD`, `decimals` must be at least `1`, since that number has a single decimal place.
|
|
|
|
How can this be achieved? It's actually very simple: a token contract can use larger integer values, so that a balance of `50` will represent `5 GLD`, a transfer of `15` will correspond to `1.5 GLD` being sent, and so on.
|
|
|
|
It is important to understand that `decimals` is _only used for display purposes_. All arithmetic inside the contract is still performed on integers, and it is the different user interfaces (wallets, exchanges, etc.) that must adjust the displayed values according to `decimals`. The total token supply and balance of each account are not specified in `GLD`: you need to divide by `10^decimals` to get the actual `GLD` amount.
|
|
|
|
You'll probably want to use a `decimals` value of `18`, just like Ether and most ERC20 token contracts in use, unless you have a very special reason not to. When minting tokens or transferring them around, you will be actually sending the number `num GLD * 10^decimals`.
|
|
|
|
NOTE: By default, `ERC20` uses a value of `18` for `decimals`. To use a different value, you will need to call xref:api:token/ERC20.adoc#ERC20-_setupDecimals-uint8-[_setupDecimals] in your constructor.
|
|
|
|
So if you want to send `5` tokens using a token contract with 18 decimals, the the method to call will actually be:
|
|
|
|
```solidity
|
|
transfer(recipient, 5 * 10^18);
|
|
```
|
|
|
|
[[Presets]]
|
|
== Preset ERC20 contract
|
|
A preset ERC20 is available, xref:api:presets#ERC20PresetMinterPauser[`ERC20PresetMinterPauser`]. It is preset to allow for token minting (create), stop all token transfers (pause) and allow holders to burn (destroy) their tokens. The contract uses xref:access-control.adoc[Access Control] to control access to the minting and pausing functionality. The account that deploys the contract will be granted the minter and pauser roles, as well as the default admin role.
|
|
|
|
This contract is ready to deploy without having to write any Solidity code. It can be used as-is for quick prototyping and testing, but is also suitable for production environments.
|