I modified the script so that initialize is called in a separate transaction.
Though we should initialize as part of creating the proxy, otherwise anyone can create a transaction that calls initialize.
const Web3 = require('web3');
const { Contracts, ProxyAdminProject, ZWeb3 } = require('@openzeppelin/upgrades')
async function main() {
// Create web3 provider and initialize OpenZeppelin upgrades
const web3 = new Web3('http://localhost:8545');
ZWeb3.initialize(web3.currentProvider)
// Create an OpenZeppelin project
const [from] = await ZWeb3.eth.getAccounts();
const project = new ProxyAdminProject('MyProject', null, null, { from, gas: 1e6, gasPrice: 1e9 });
// Deploy an instance of MyContractV0
console.log('Creating an upgradeable instance of v0...');
const MyContractV0 = Contracts.getFromLocal('MyContractV0');
//const instance = await project.createProxy(MyContractV0, { initArgs: [42] });
const instance = await project.createProxy(MyContractV0);
await instance.methods.initialize(42).send();
const address = instance.options.address;
console.log(`Contract created at ${address}`);
// And check its initial value
const initialValue = await instance.methods.value().call();
console.log(`Initial value is ${initialValue.toString()}\n`);
// Upgrade it to V1
console.log('Upgrading to v1...');
const MyContractV1 = Contracts.getFromLocal('MyContractV1');
const instanceV1 = await project.upgradeProxy(instance.options.address, MyContractV1);
console.log(`Contract upgraded at ${instanceV1.options.address}`);
// And check its new `add` method, note that we use instanceV1 since V0 has no `add` in its ABI
await instanceV1.methods.add(10).send({ from, gas: 1e5, gasPrice: 1e9 });
const newValue = await instance.methods.value().call();
console.log(`Updated value is ${newValue.toString()}\n`);
}
main();
const MyContract = Contracts.getFromNodeModules('@openzeppelin/contracts-ethereum-package', 'ERC20PresetMinterPauserUpgradeSafe');
const initialSupply = web3.utils.toWei('240', 'ether');
const tokenName = 'Name_test';
const tokenSymbol = 'Symbol_test';
contract('tokenTest', function ([admin, anotherAccount, recipient]) {
beforeEach(async function () {
this.project = await TestHelper();
this.proxy = await this.project.createProxy(MyContract, { initMethod: 'initialize', initArgs: [tokenName, tokenSymbol] });
await this.proxy.methods.mint(admin, initialSupply).send();
})
describe('initialize', function () {
it('should initilize the contract if it was not initialize', async function () {
const newProxy = await this.project.createProxy(MyContract);
await newProxy.methods.initialize(tokenName, tokenSymbol).send();
})
it('should not be able to initialize the contract more than once', async function () {
await expectRevert(this.proxy.methods.initialize(tokenName, tokenSymbol).send(),
'transaction: revert Contract instance has already been initialized'
);
})
})
})
This is what I have been using, all my tests work the first initialize() function is the only one failing. moreover, when I manually use the SDK to deploy ERC20PresetMinterPauserUpgradeSafe and then try to use truffle/web3 to initialize the contract I get a revert.
When I create the proxy via the SDK I can then call later the function initialize() with "npx oz send-tx"
So I guess there must be a way or m'I not understanding this right?
? Pick a contract to deploy @openzeppelin/contracts-ethereum-package/ERC20PresetMinterPauserUpgradeSafe
All implementations are up to date
? Call a function to initialize the instance after creating it? No
Possible initialization method (initialize) found in contract. Make sure you initialize your instance.
✓ Instance created at 0x8A15026B0b594C295bef7E40204AA87CF4adac01
To upgrade this instance run 'oz upgrade'
0x8A15026B0b594C295bef7E40204AA87CF4adac01
? Pick a network development
? Pick an instance ERC20PresetMinterPauserUpgradeSafe at 0x8A15026B0b594C295bef7E40204AA87CF4adac01
? Select which function initialize(name: string, symbol: string)
? name: string: name_test
? symbol: string: SMB
✓ Transaction successful. Transaction hash: 0xeeb4d424bd2b769885a1007e1c293ee3e2382515535ca6fdda423fae21ef8f51
I don't know if this was discussed previously. I think the concern would be adding complexity, when the best practice is calling initialize when the proxy is created.