Immutable ZkEvm Testnet - Upgradeable Contract initialize not being called

Trying to create upgradeable contracts using hardhat and OpenZeppelin Upgrades but, when calling either the deploy or upgrade script, initialize is not called (values show up as default when i check the contract in the explorer)

These are the scripts:

Deploy

import { ethers, upgrades } from 'hardhat';

import { getImplementationAddress } from '@openzeppelin/upgrades-core';

async function main() {
	const WageringContract = await ethers.getContractFactory('WageringContract');
	const wageringContract = await upgrades.deployProxy(
		WageringContract,
		[
			'0xc2dd1910ca7fe8b18d315b77bd56406e9d9764ee',
			'0xc2dd1910ca7fe8b18d315b77bd56406e9d9764ee',
			'0xc2dd1910ca7fe8b18d315b77bd56406e9d9764ee',
			'0xc2dd1910ca7fe8b18d315b77bd56406e9d9764ee',
			3,
			3,
			'0x40af4101c5cdd511b76b28dad188e5041ecf6d4f',
			'0xc2dd1910ca7fe8b18d315b77bd56406e9d9764ee',
		],
		{ initializer: 'initialize', kind: 'uups' }
	);
	await wageringContract.waitForDeployment();
	console.log(
		'Wagering proxy deployed to:',
		await wageringContract.getAddress()
	);
	console.log(
		'Wagering implementation deployed to:',
		await getImplementationAddress(
			ethers.provider,
			await wageringContract.getAddress()
		)
	);
}

main();

And upgrade, which errors:

import { ethers, upgrades } from 'hardhat';

import { getImplementationAddress } from '@openzeppelin/upgrades-core';

const main = async (): Promise<void> => {
	const NewWageringVersion = await ethers.getContractFactory('WageringV4');
	console.log('Upgrading Wagering...');
	await upgrades.upgradeProxy(
		'0xdCE475eEdF0198abb33C59e384beC861ABbEc2CB',
		NewWageringVersion,
		{
			kind: 'uups',
			call: {
				fn: 'initialize',
				args: [
					'0xc2dd1910ca7fe8b18d315b77bd56406e9d9764ee',
					'0xc2dd1910ca7fe8b18d315b77bd56406e9d9764ee',
					'0xc2dd1910ca7fe8b18d315b77bd56406e9d9764ee',
					'0xc2dd1910ca7fe8b18d315b77bd56406e9d9764ee',
					3,
					3,
					'0x40af4101c5cdd511b76b28dad188e5041ecf6d4f',
					'0xc2dd1910ca7fe8b18d315b77bd56406e9d9764ee',
				],
			},
		}
	);
	console.log('Wagering upgraded');
	console.log(
		'New wagering implementation deployed to:',
		await getImplementationAddress(
			ethers.provider,
			'0xdCE475eEdF0198abb33C59e384beC861ABbEc2CB'
		)
	);
};

main()

This is the error for the upgrade:

Can you share your proxy and implementation addresses / links to the block explorer? Note the initializer should be called on the proxy address, not the implementation address.

So, the call options in the upgradeProxy calls a function on the implementation, not the proxy?

And btw, how would the proxy show as verified on blockscout, so it shows the implementation methods?

Thanks.

Edit:
Would this be it? Still errors.

import { ethers, upgrades } from 'hardhat';

import { getImplementationAddress } from '@openzeppelin/upgrades-core';

const main = async (): Promise<void> => {
	const NewWageringVersion = await ethers.getContractFactory('WageringV4');
	console.log('Upgrading Wagering...');
	await upgrades.upgradeProxy(
		'0xdCE475eEdF0198abb33C59e384beC861ABbEc2CB',
		NewWageringVersion,
		{
			kind: 'uups',
		}
	);
	console.log('Wagering upgraded');

	let proxiedWagering = NewWageringVersion.attach(
		'0xdCE475eEdF0198abb33C59e384beC861ABbEc2CB'
	);
	await proxiedWagering.initialize(
		'0xc2dd1910ca7fe8b18d315b77bd56406e9d9764ee',
		'0xc2dd1910ca7fe8b18d315b77bd56406e9d9764ee',
		'0xc2dd1910ca7fe8b18d315b77bd56406e9d9764ee',
		'0xc2dd1910ca7fe8b18d315b77bd56406e9d9764ee',
		3,
		3,
		'0x40af4101c5cdd511b76b28dad188e5041ecf6d4f',
		'0xc2dd1910ca7fe8b18d315b77bd56406e9d9764ee'
	);

	console.log('Wagering reinitialized');

	console.log(
		'New wagering implementation deployed to:',
		await getImplementationAddress(
			ethers.provider,
			'0xdCE475eEdF0198abb33C59e384beC861ABbEc2CB'
		)
	);
};

main();

Also tried importing the WageringV4 contract type because attach was not assuming the contract type.

The call options on upgradeProxy calls a function at the proxy address (but the function is defined in the implementation contract).

It looks like you can see the implementation methods in the "Read/Write proxy" tab of your proxy here.

It shows the implementation address as 0xF77E39069c9297d52e83295B5fa2d77823c7cceB.

You can see in the creation transaction of your proxy, it logged Initialized in the logs at log index 5. So it did run the initializer.

Hmmn, so why would it error during the call but still go through?

Here is the most recent upgradeToAndCall transaction that I can see on your proxy: https://explorer.testnet.immutable.com/tx/0x6c6ef57cda1b064f5c56485e7cf56fe53aafa78247b48aab2d285acbcbd05cef

This transaction has set 0xF77E39069c9297d52e83295B5fa2d77823c7cceB as the implementation, but you can see that the data parameter in the 'Decoded input data" is 0x. This means that no additional function was called.

From your script, it looks like you are trying to call the initializer again on the new version, after the upgrade. This initializer call should not work, because your proxy is already initialized.

Consider using a reinitializer in your new version if needed. See Difference between initializer, reinitializer(1), and reinitializer(2) modifiers

Also consider using the call option of upgradeProxy so that the reinitializer call is done in the same transaction as the upgrade. See https://docs.openzeppelin.com/upgrades-plugins/1.x/api-hardhat-upgrades#upgrade-proxy

Ok, sounds good.

Thanks for the help, so in the upgradeProxy i cant call initialize, would need a reinitialize function from what I understand.

This was just for me to understand because I dont really need to reinitialize right now since I also have set functions for all the parameters i initialized.

1 Like