I've ran into the same issue myself and I'm able to reproduce.
mkdir repro && cd repro
npm init -y
npm i --save-dev truffle &&
npm i --save-dev @openzeppelin/truffle-upgrades &&
npm i --save-dev @openzeppelin/contracts-ethereum-package &&
npm i --save-dev @truffle/hdwallet-provider
If you are from the future it is already fixed and you want to reproduce use these:
"devDependencies": {
"@openzeppelin/contracts-ethereum-package": "^3.0.0",
"@openzeppelin/truffle-upgrades": "^1.2.0",
"@truffle/hdwallet-provider": "^1.1.1",
"truffle": "^5.1.49"
}
-
npx truffle init
-
Copy-paste content into files
// contracts/Coin.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.6.0;
import "@openzeppelin/contracts-ethereum-package/contracts/Initializable.sol";
import "@openzeppelin/contracts-ethereum-package/contracts/presets/ERC20PresetMinterPauser.sol";
contract Coin is ERC20PresetMinterPauserUpgradeSafe {
bytes32 public constant WHITELIST_ROLE = keccak256("WHITELIST_ROLE");
modifier onlyWhitelister {
require(hasRole(WHITELIST_ROLE, _msgSender()), "must have WHITELIST ROLE");
_;
}
function initialize(string memory name, string memory symbol) public override virtual initializer {
ERC20PresetMinterPauserUpgradeSafe.initialize(name, symbol);
_setupRole(WHITELIST_ROLE, _msgSender());
}
}
// test/coin.js
function toWei(eth){
return web3.utils.toWei(eth);
}
const Coin = artifacts.require('Coin');
contract('Coin ', async function(accounts) {
const creator = accounts[0]
const user1 = accounts[1];
const user2 = accounts[2];
let coin;
beforeEach(async function() {
coin= await Coin.new({ from: creator } );
await coin.initialize("Sample Coin", "SC ", { from: creator } );
await coin.mint(user1, toWei("200000"), { from: creator });
})
it('User 1 should be able to send tokens to User 2', async () => {
await coin.transfer(user2, toWei("10"), { from: user1 })
assert.equal(await coin.balanceOf(user2), toWei("10"), "User 2 does not have 10 tokens");
});
})
Some housekeeping otherwise the compiler will complain:
- Compiler version in
truffle-config.js
should becompilers: { solc: { version: "^0.6.0" } }
(line 85) - Add
virtual
to theinitialize
function innode_modules\@openzeppelin\contracts-ethereum-package\contracts\presets\ERC20PresetMinterPauser.sol
(line 35)
DONE-ish. Can run truffle test
, it compiles, it works, it pass the test...
So far so good...
...now this is failing.
// migrations/2_breaking_migration.js
const Coin = artifacts.require('Coin');
const { deployProxy } = require('@openzeppelin/truffle-upgrades');
module.exports = async function (deployer) {
await deployProxy(Coin, ["New token", "NTKN"], { deployer, initializer: 'initialize', unsafeAllowCustomTypes : true });
};
Error: Artifacts are from different compiler runs
Run a full recompilation usingtruffle compile --all
https://zpl.in/upgrades/truffle-recompile-all
Deleting the build folder / recompiling does not help.
I think it has something to do with some of the contracts being precompiled, see this post: Add instructions on how to verify to Upgrades Plugins step by step guides - #2 by abcoathup
It works on Mac BTW.