Why is initialize defined twice in StandaloneERC20

Does anyone know why the function initialize is defined twice?
Do we have to follow the same standard?

pragma solidity ^0.5.0;

import "@openzeppelin/upgrades/contracts/Initializable.sol";
import "./ERC20Detailed.sol";
import "./ERC20Mintable.sol";
import "./ERC20Pausable.sol";


/**
 * @title Standard ERC20 token, with minting and pause functionality.
 *
 */
contract StandaloneERC20 is Initializable, ERC20Detailed, ERC20Mintable, ERC20Pausable {
    function initialize(
        string memory name, string memory symbol, uint8 decimals, uint256 initialSupply, address initialHolder,
        address[] memory minters, address[] memory pausers
    ) public initializer {
        ERC20Detailed.initialize(name, symbol, decimals);

        // Mint the initial supply
        _mint(initialHolder, initialSupply);

        // Initialize the minter and pauser roles, and renounce them
        ERC20Mintable.initialize(address(this));
        _removeMinter(address(this));

        ERC20Pausable.initialize(address(this));
        _removePauser(address(this));

        // Add the requested minters and pausers (this can be done after renouncing since
        // these are the internal calls)
        for (uint256 i = 0; i < minters.length; ++i) {
            _addMinter(minters[i]);
        }

        for (uint256 i = 0; i < pausers.length; ++i) {
            _addPauser(pausers[i]);
        }
    }

    function initialize(
        string memory name, string memory symbol, uint8 decimals, address[] memory minters, address[] memory pausers
    ) public initializer {
        ERC20Detailed.initialize(name, symbol, decimals);

        // Initialize the minter and pauser roles, and renounce them
        ERC20Mintable.initialize(address(this));
        _removeMinter(address(this));

        ERC20Pausable.initialize(address(this));
        _removePauser(address(this));

        // Add the requested minters and pausers (this can be done after renouncing since
        // these are the internal calls)
        for (uint256 i = 0; i < minters.length; ++i) {
            _addMinter(minters[i]);
        }

        for (uint256 i = 0; i < pausers.length; ++i) {
            _addPauser(pausers[i]);
        }
    }
}
1 Like

Hi @pkr,

The difference between the two initialize functions is that the first takes an initialHolder and an initialSupply parameters and then mints an initial supply of tokens.

// Mint the initial supply
_mint(initialHolder, initialSupply);

This avoids having to call an explicit mint after the initialize.

Contracts inheriting from StandaloneERC20 do not need to override the two functions, only the functions required, or create their own token inheriting fromERC20Detailed and any other components such as ERC20Mintable.

Thank you, that difference in the # of parameters between the 1st and 2nd initialize clears things a bit.

A bit confused here …a bit more explanation would help.

Hi @pkr,

Given that you are creating your token from a factory, you may want to create a token that inherits from StandaloneERC20 and then overrides one of the initialize functions that you need (if you need to override at all).

You may even create your own token contract based on StandaloneERC20.

Let me know if you need more information.

1 Like