Hi. I have a weird thing here where my code sometimes reverts in truffle test
, sometimes not.
When it reverts, it always revert
at the line where “addMinter” is executed on the CrowdSale-Contract out of “beforeEach” in the test (which can be seen with the output of console.log(5)
. After “5” was printed to stdout, it reverts. When I would debug this with “truffle debug $transactionID”, everything would go through.
When I run these tests 5 times, then there is a big chance that at least for one time it reverts with the very first test, sometimes at the second or third test, sometimes everything is going through without any revert.
When I run these tests 10 times, in some cases everything works fine, and mostly it breaks within a particular test like described above.
Could it be a Gas issue? The repository can be found here: https://github.com/itinance/ncd-token
contract("CrowdSale tests", async ([_, owner, pauser1, pauser2, ...otherAccounts]) => {
let token, tokenSale,
openingTime, closingTime, afterClosingTime;
const buyer = otherAccounts[1];
beforeEach(async function () {
token = await XXXToken.new({from: owner});
token.initialize( owner, [pauser1, pauser2]);
openingTime = await time.latest();
closingTime = openingTime.add(time.duration.years(1));
afterClosingTime = closingTime.add(time.duration.seconds(1));
console.log(4, token.address);
tokenSale = await XXXTokenSale.new({from: owner});
tokenSale.initialize(openingTime, closingTime, token.address);
console.log(5)
await token.addMinter(tokenSale.address, {from: owner});
console.log(6)
await token.renounceMinter({ from: owner });
console.log(7)
});
it('crowdsale should be minter', async function () {
(await token.isMinter(tokenSale.address)).should.equal(true);
});
it('owner should not be minter anymore', async function () {
(await token.isMinter(owner)).should.equal(false);
});
it('Timelock can be added', async function() {
await tokenSale.addTimelock(afterClosingTime);
})
});
I have already found out, that when I encapsulate the tests within a nested
describe("Initiating token sale", function() {
// lets move tests here
}
then less reverts will happen, but still do.
I run on MacbookPro with MacOS Mojave and the following toolset:
$ truffle version
Truffle v5.0.20 (core: 5.0.20)
Solidity v0.5.0 (solc-js)
Node v10.16.0
Web3.js v1.0.0-beta.37
Ganache CLI v6.3.0 (ganache-core: 2.4.0)
Ganache was launched this way:
ganache-cli --mnemonic “your twelve word mnemonic here”
truffle-config.js:
module.exports = {
// See http://truffleframework.com/docs/advanced/configuration
// to customize your Truffle configuration!
networks: {
development: {
host: “127.0.0.1”,
port: 8545,
gas: 6000000,
gasPrice: 5e9,
network_id: "*",
},
For the sake of completeness the code of token contract:
contract XXXToken is ERC20Detailed, ERC20Mintable, ERC20Pausable {
function initialize(
address minter,
address[] memory pausers
) public initializer {
require(pausers[0] != address(0));
ERC20Detailed.initialize("XXXToken", "XXX", uint8(18));
ERC20Mintable.initialize(minter);
ERC20Pausable.initialize(pausers[0]);
// add the other pausers as well if existing
for (uint256 i = 1; i < pausers.length; ++i) {
_addPauser(pausers[i]);
}
}
function () external payable {
revert();
}
/**
* @dev Minting tokens
* @param account The account of beneficiary who will get the minted token
* @param value The amount of minted token
*/
function _mint(address account, uint256 value) internal whenNotPaused onlyMinter {
super._mint(account, value);
}
}
And the CrowdSale contract:
contract XXXTokenSale is Initializable, Ownable {
using SafeMath for uint256;
XXXToken private _token;
uint256 private _openingTime;
uint256 private _closingTime;
uint256 private _mintedTokens;
TokenTimelock private _timeLock;
/**
* @dev Reverts if not in crowdsale time range.
*/
modifier onlyWhileOpen {
require(isOpen());
_;
}
TeamVesting private _teamVesting;
event TeamVestingAssigned(address teamVesting);
function initialize(uint256 openingTime, uint256 closingTime, XXXToken token) public initializer {
require(address(token) != address(0));
_token = token;
// solhint-disable-next-line not-rely-on-time
require(openingTime >= block.timestamp);
require(closingTime > openingTime);
_openingTime = openingTime;
_closingTime = closingTime;
}
function addTimelock(uint256 releaseTime) public {
_timeLock = new TokenTimelock();
_timeLock.initialize(_token, address(_teamVesting), releaseTime );
}
/**
* @return the token being sold.
*/
function token() public view returns (XXXToken) {
return _token;
}
function mintedTokens() public view returns (uint256) {
return _mintedTokens;
}
/**
* @return true if the crowdsale is open, false otherwise.
*/
function isOpen() public view returns (bool) {
// solhint-disable-next-line not-rely-on-time
return block.timestamp >= _openingTime && block.timestamp <= _closingTime;
}
/**
* @dev Checks whether the period in which the crowdsale is open has already elapsed.
* @return Whether crowdsale period has elapsed
*/
function hasClosed() public view returns (bool) {
// solhint-disable-next-line not-rely-on-time
return block.timestamp > _closingTime;
}
function assignTeamVesting(TeamVesting teamVesting) public onlyOwner {
require(address(teamVesting) != address(0));
_teamVesting = teamVesting;
emit TeamVestingAssigned(address(teamVesting));
}
function () external payable {
revert();
}
/**
* @dev Overrides delivery by minting tokens upon purchase.
* @param beneficiary Token purchaser
* @param tokenAmount Number of tokens to be minted
*/
function mintTokens(address beneficiary, uint256 tokenAmount) public onlyWhileOpen {
_mintedTokens = _mintedTokens.add(tokenAmount);
require(XXXToken(address(token())).mint(beneficiary, tokenAmount));
}
}
Has anybody faced this issue and can tell a workaround?