Contract not setting constructor parameters and gas error when interacting with the contract

Hi community,
I deployed this contract:

pragma solidity ^0.5.0;

import "@openzeppelin/contracts/token/ERC20/ERC20Detailed.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20Mintable.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20Pausable.sol";

contract FarmaCoin is ERC20Pausable, ERC20Burnable, ERC20Mintable, ERC20Detailed {

    constructor () public ERC20Detailed("FarmaCoin", "FC", 2) { }
    function transfer(address to, uint256 value) public returns (bool) {
        return super.transfer(to, value);     }
 
     function transferFrom(address from, address to, uint256 value) public returns (bool) {
         return super.transferFrom(from, to, value);
     }
 
     function approve(address spender, uint256 value) public returns (bool) {
         return super.approve(spender, value);
     }
 
     function increaseAllowance(address spender, uint256 addedValue) public returns (bool) {
         return super.increaseAllowance(spender, addedValue);
     }
 
     function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) {
         return super.decreaseAllowance(spender, subtractedValue);
     }
 
     function burn(uint256 amount) public {
         return super.burn(amount);
     }
 
     function burnFrom(address account, uint256 amount) public {
         super.burnFrom(account, amount);
     }
 
     function mint(address account, uint256 amount) public returns (bool) {
         return super.mint(account, amount);
     }
 
 }

Deployment goes fine, I use oz create on a Quorum private blockchain.
Two issues after,when trying to interact with this contract:

  • If I test oz call name, symbol and decimal returnn null values
  • If try to execute a transaction on this contract, for isntance calling mint() or addMinter() functions to start putting some tokens in circulation… or any other transactions on the contract I get this error:
    Error while trying to send transaction to 0xbc89726802FF4C9dB5fA87be96a67444480F95aE. Error: Error: Returned error: gas required exceeds allowance or always failing transaction
1 Like

Hi @rtraba,

I am sorry that you are having problems.

The reason why this wasn’t working is that OpenZeppelin SDK is for creating upgradeable contracts, and the Token you posted is a non-upgradeable contract. Apologies that this is confusing.
I have created an issue to warn users: https://github.com/OpenZeppelin/openzeppelin-sdk/issues/1297.
There is also a plan to remove this requirement: Planning the demise of OpenZeppelin Contracts' evil twin.

https://docs.openzeppelin.com/sdk/2.5/writing-contracts
You can use your Solidity contracts in the OpenZeppelin SDK without any modifications, except for their constructors . Due to a requirement of the proxy-based upgradeability system, no constructors can be used in upgradeable contracts.

To create an upgradeable token using OpenZeppelin SDK then we need to use @openzeppelin/contracts-ethereum-package otherwise we can create a non-upgradeable token and deploy using truffle.

https://docs.openzeppelin.com/sdk/2.5/linking
NOTE: Make sure you install @openzeppelin/contracts-ethereum-package and not the vanilla @openzeppelin/contracts . The latter is set up for general usage, while @openzeppelin/contracts-ethereum-package is tailored for being used with the OpenZeppelin SDK. This means that its contracts are already set up to be upgradeable.

Example

In an OpenZeppelin SDK project (see Your first project for setup)

Link OpenZeppelin Contracts Ethereum Package and install @openzeppelin/upgrades

openzeppelin link @openzeppelin/contracts-ethereum-package
npm install @openzeppelin/upgrades

SimpleToken.sol

Upgradeable SimpleToken

pragma solidity ^0.5.0;

import "@openzeppelin/upgrades/contracts/Initializable.sol";

import "@openzeppelin/contracts-ethereum-package/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts-ethereum-package/contracts/token/ERC20/ERC20Detailed.sol";

/**
 * @title SimpleToken
 * @dev Very simple ERC20 Token example, where all tokens are pre-assigned to the sender.
 * Note they can later distribute these tokens as they wish using `transfer` and other
 * `ERC20` functions.
 */
contract SimpleToken is Initializable, ERC20, ERC20Detailed {

    /**
     * @dev initialize that gives msg.sender all of existing tokens.
     */
    function initialize(address sender) public initializer {
        ERC20Detailed.initialize("Token", "TKN", 18);
        _mint(sender, 1000000 * (10 ** uint256(decimals())));
    }
}

If you need assistance with a mintable/burnable contract let me know.


As an aside, I assume there was a reason for overriding functions such as approve and transferFrom.

Thnaks, @abcoathup
I tried to deploy your simple token for testing upgradability and I've some questions. See this:

oz create

Nothing to compile, all contracts are up to date.
? Pick a contract to instantiate SimpleToken
Using session with network farmapago_dev_5, sender address 0xCB08D43a9bCaec981b44508Bdb3aBb7311382ed7, timeout 3600 seconds
âś“ Added contract SimpleToken
? One or more linked dependencies are not yet deployed on dev-10.
Do you want to deploy them now? Yes
âś“ Deploying @openzeppelin/contracts-ethereum-package dependency to network dev-10
âś“ Contract SimpleToken deployed
All contracts have been deployed
? Call a function to initialize the instance after creating it? Yes
? Select which function * initialize(name: string, symbol: string, decimals: uint8)
? name (string): Upgredable Token
? symbol (string): UT
? decimals (uint8): 2
âś“ Setting everything up to create contract instances
âś“ Instance created at 0x746747853C2d670af96Ba9B61b75C7774d18250e
0x746747853C2d670af96Ba9B61b75C7774d18250e

But then, when when I try to call functions to read totalSupply or getting balance just nothing is there, see this:

oz call
Using session with network farmapago_dev_5, sender address 0xCB08D43a9bCaec981b44508Bdb3aBb7311382ed7, timeout 3600 seconds
? Pick an instance SimpleToken at 0x746747853C2d670af96Ba9B61b75C7774d18250e
? Select which function totalSupply()
âś“ Method 'totalSupply()' returned: 0
0

or this:

oz call
Using session with network farmapago_dev_5, sender address 0xCB08D43a9bCaec981b44508Bdb3aBb7311382ed7, timeout 3600 seconds
? Pick an instance SimpleToken at 0x746747853C2d670af96Ba9B61b75C7774d18250e
? Select which function balanceOf(account: address)
? account (address): 0xCB08D43a9bCaec981b44508Bdb3aBb7311382ed7
âś“ Method 'balanceOf(address)' returned: 0
0

but if I get for example, decimals or name o symbol, it actually works fine:

oz call
Using session with network farmapago_dev_5, sender address 0xCB08D43a9bCaec981b44508Bdb3aBb7311382ed7, timeout 3600 seconds
? Pick an instance SimpleToken at 0x746747853C2d670af96Ba9B61b75C7774d18250e
? Select which function decimals()
âś“ Method 'decimals()' returned: 2
2

I understand than because we are interacting with upgradable contracts I should execute explicitly Initialize() functions (from this and super) just one time after contract creation. In other hand, when the contract is already deployed oz ask if I want to initialize the contract and let me execute any function. In simpletoken example you proivided it looks like this:

oz create
Nothing to compile, all contracts are up to date.
? Pick a contract to instantiate SimpleToken
Using session with network farmapago_dev_5, sender address 0xCB08D43a9bCaec981b44508Bdb3aBb7311382ed7, timeout 3600 seconds
All contracts are up to date
? Call a function to initialize the instance after creating it? Yes
? Select which function (Use arrow keys)
❯ * initialize(name: string, symbol: string, decimals: uint8)

  • initialize(sender: address)
    approve(spender: address, amount: uint256)
    decreaseAllowance(spender: address, subtractedValue: uint256)
    increaseAllowance(spender: address, addedValue: uint256)
    transfer(recipient: address, amount: uint256)
    transferFrom(sender: address, recipient: address, amount: uint256)

So oz doesn't treat initializer functions as special type of functions... I could be executing any functions before calling initializers??? another tricky thing is that it shows both initializers, from the contract that is being deployed and from parents, so there is no warranty of execution order and we need to see parent's code to know exactly which is the function that we really want to invoke. In fact in my first simpletoken deployment I executed initialize(name: string, symbol: string, decimals: uint8) instead of initialize(sender: address) and I think that is why minting hasn't been executed.

1 Like

If I try to execute initialize(sender: address) after parent initialize function has been already executed, I get this:

oz send-tx
Using session with network farmapago_dev_5, sender address 0xCB08D43a9bCaec981b44508Bdb3aBb7311382ed7, timeout 3600 seconds
? Pick an instance SimpleToken at 0x746747853C2d670af96Ba9B61b75C7774d18250e
? Select which function * initialize(sender: address)
? sender (address): 0xCB08D43a9bCaec981b44508Bdb3aBb7311382ed7
:heavy_multiplication_x: Calling: 'initialize' with:

  • sender (address): "0xCB08D43a9bCaec981b44508Bdb3aBb7311382ed7"
    Error while trying to send transaction to 0x746747853C2d670af96Ba9B61b75C7774d18250e. Error: Error: Returned error: gas required exceeds allowance or always failing transaction

I can not see direct causal relation from the error and the fact tha initializers has been executed in wrong order... but maybe I'm missing something there.

1 Like

Hi @rtraba,

The SimpleToken example above uses an initialize with a single address parameter.

contract SimpleToken is Initializable, ERC20, ERC20Detailed {

    function initialize(address sender) public initializer {
        ERC20Detailed.initialize("Token", "TKN", 18);
        _mint(sender, 1000000 * (10 ** uint256(decimals())));
    }
}

As you guessed, you need to call initialize(sender: address) to initialize SimpleToken, see example below:

$ oz create
âś“ Compiled contracts with solc 0.5.13 (commit.5b0b510c)
? Pick a contract to instantiate SimpleToken
? Pick a network development
âś“ Added contract SimpleToken
âś“ Deploying @openzeppelin/contracts-ethereum-package dependency to network dev-1575252994947
âś“ Contract SimpleToken deployed
All contracts have been deployed
? Call a function to initialize the instance after creating it? Yes
? Select which function * initialize(sender: address)
? sender (address): 0xc659c73b2eac5C58E48c596175E9c61FE2CB029b
âś“ Setting everything up to create contract instances
âś“ Instance created at 0xAF62e034C5361C6f62f99a313C06B661BB07D957
0xAF62e034C5361C6f62f99a313C06B661BB07D957

The initializer modifier prevents any functions with this modifier being called more than once.

See the documentation on initializer's for more details: https://docs.openzeppelin.com/sdk/2.6/writing-contracts#initializers

Hey @rtraba! Starting with 2.7 RC, the OpenZeppelin CLI will warn if you try to use the vanilla @openzeppelin/contracts instead of @openzeppelin/contracts-ethereum-package. This is temporary though, as we are working on unifying both of them. Give the new RC a try and let us know what you think!

1 Like

Hi @rtraba,

The CLI now supports deploying regular (non-upgradeable) contracts in the release candidate of OpenZeppelin CLI 2.8

Would appreciate if you could give the release candidate a try and let us know what you think!