You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
71 lines
4.0 KiB
71 lines
4.0 KiB
= Creating ERC-20 Supply
|
|
|
|
In this guide, you will learn how to create an ERC-20 token with a custom supply mechanism. We will showcase two idiomatic ways to use OpenZeppelin Contracts for this purpose that you will be able to apply to your smart contract development practice.
|
|
|
|
The standard interface implemented by tokens built on Ethereum is called ERC-20, and Contracts includes a widely used implementation of it: the aptly named xref:api:token/ERC20.adoc[`ERC20`] contract. This contract, like the standard itself, is quite simple and bare-bones. In fact, if you try to deploy an instance of `ERC20` as-is it will be quite literally useless... it will have no supply! What use is a token with no supply?
|
|
|
|
The way that supply is created is not defined in the ERC-20 document. Every token is free to experiment with its own mechanisms, ranging from the most decentralized to the most centralized, from the most naive to the most researched, and more.
|
|
|
|
[[fixed-supply]]
|
|
== Fixed Supply
|
|
|
|
Let's say we want a token with a fixed supply of 1000, initially allocated to the account that deploys the contract. If you've used Contracts v1, you may have written code like the following:
|
|
|
|
[source,solidity]
|
|
----
|
|
contract ERC20FixedSupply is ERC20 {
|
|
constructor() {
|
|
totalSupply += 1000;
|
|
balances[msg.sender] += 1000;
|
|
}
|
|
}
|
|
----
|
|
|
|
Starting with Contracts v2, this pattern is not only discouraged, but disallowed. The variables `totalSupply` and `balances` are now private implementation details of `ERC20`, and you can't directly write to them. Instead, there is an internal xref:api:token/ERC20.adoc#ERC20-_mint-address-uint256-[`_mint`] function that will do exactly this:
|
|
|
|
[source,solidity]
|
|
----
|
|
contract ERC20FixedSupply is ERC20 {
|
|
constructor() ERC20("Fixed", "FIX") {
|
|
_mint(msg.sender, 1000);
|
|
}
|
|
}
|
|
----
|
|
|
|
Encapsulating state like this makes it safer to extend contracts. For instance, in the first example we had to manually keep the `totalSupply` in sync with the modified balances, which is easy to forget. In fact, we omitted something else that is also easily forgotten: the `Transfer` event that is required by the standard, and which is relied on by some clients. The second example does not have this bug, because the internal `_mint` function takes care of it.
|
|
|
|
[[rewarding-miners]]
|
|
== Rewarding Miners
|
|
|
|
The internal xref:api:token/ERC20.adoc#ERC20-_mint-address-uint256-[`_mint`] function is the key building block that allows us to write ERC-20 extensions that implement a supply mechanism.
|
|
|
|
The mechanism we will implement is a token reward for the miners that produce Ethereum blocks. In Solidity, we can access the address of the current block's miner in the global variable `block.coinbase`. We will mint a token reward to this address whenever someone calls the function `mintMinerReward()` on our token. The mechanism may sound silly, but you never know what kind of dynamic this might result in, and it's worth analyzing and experimenting with!
|
|
|
|
[source,solidity]
|
|
----
|
|
contract ERC20WithMinerReward is ERC20 {
|
|
constructor() ERC20("Reward", "RWD") {}
|
|
|
|
function mintMinerReward() public {
|
|
_mint(block.coinbase, 1000);
|
|
}
|
|
}
|
|
----
|
|
|
|
As we can see, `_mint` makes it super easy to do this correctly.
|
|
|
|
[[automating-the-reward]]
|
|
== Automating the Reward
|
|
|
|
So far our supply mechanism was triggered manually, but `ERC20` also allows us to extend the core functionality of the token through the xref:api:token/ERC20.adoc#ERC20-_update-address-address-uint256-[`_update`] function.
|
|
|
|
Adding to the supply mechanism from the previous section, we can use this function to mint a miner reward for every token transfer that is included in the blockchain.
|
|
|
|
```solidity
|
|
include::api:example$ERC20WithAutoMinerReward.sol[]
|
|
```
|
|
|
|
[[wrapping-up]]
|
|
== Wrapping Up
|
|
|
|
We've seen how to implement a ERC-20 supply mechanism: internally through `_mint`. Hopefully this has helped you understand how to use OpenZeppelin Contracts and some of the design principles behind it, and you can apply them to your own smart contracts.
|
|
|