You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I'm encountering an issue when using the OpenZeppelin proxy pattern. Specifically, the upgradeToAndCall function in ERC1967Utils.sol fails to correctly initialize my contract using functionDelegateCall.
Problem Description
I am using the following setup:
Contract: TestContractUpgradableV1
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./contracts/proxy/utils/Initializable.sol";
contract TestContractUpgradableV1 is Initializable {
uint256 public constant VERSION = 1;
uint256 public bankBalances;
function initialize(uint256 _bankBalances) public initializer {
bankBalances = _bankBalances;
}
function getBalance() public view returns (uint256) {
return bankBalances;
}
}
When trying to initialize the contract during deployment via the upgradeToAndCall function, the initialization does not work as expected when passing initialization data. Specifically, calling the initialization method during the proxy contract deployment fails to execute.
Java/Web3j Code
The following code attempts to deploy a proxy and initialize the contract:
public BlockchainAddress deployProxyHandler(Wallet wallet, BlockchainAddress address) throws Exception {
Function initializeFunction = new Function(
"initialize",
Arrays.asList(new Uint256(BigInteger.valueOf(1000))),
Collections.emptyList());
String encodedInitializeFunction = FunctionEncoder.encode(initializeFunction);
byte[] encodedFunctionBytes = Numeric.hexStringToByteArray(encodedInitializeFunction);
Credentials credentials = Credentials.create(wallet.key().value());
// This works (deploys the proxy without initialization)
AdminUpgradeabilityProxy contract = AdminUpgradeabilityProxy.deploy(
web3j, credentials, new DefaultGasProvider(), BigInteger.valueOf(0),
address.value(), wallet.address().value(), new byte[0]
).send();
// These do not work (attempting to initialize during deployment)
AdminUpgradeabilityProxy.deploy(
web3j, credentials, new DefaultGasProvider(), BigInteger.valueOf(0),
address.value(), wallet.address().value(), encodedFunctionBytes
).send();
AdminUpgradeabilityProxy.deploy(
web3j, credentials, new DefaultGasProvider(), BigInteger.valueOf(0),
address.value(), wallet.address().value(), encodedInitializeFunction.getBytes()
).send();
return new BlockchainAddress(contract.getContractAddress());
}
Generated Deployment Function:
public static RemoteCall<AdminUpgradeabilityProxy> deploy(Web3j web3j, Credentials credentials,
ContractGasProvider contractGasProvider, BigInteger initialWeiValue, String logic,
String admin, byte[] data) {
String encodedConstructor = FunctionEncoder.encodeConstructor(Arrays.<Type>asList(
new org.web3j.abi.datatypes.Address(160, logic),
new org.web3j.abi.datatypes.Address(160, admin),
new org.web3j.abi.datatypes.DynamicBytes(data)));
return deployRemoteCall(AdminUpgradeabilityProxy.class, web3j, credentials, contractGasProvider, getDeploymentBinary(), encodedConstructor, initialWeiValue);
}
Expected Behavior
The expectation is that the proxy contract should be deployed and initialized in one transaction using the upgradeToAndCall method. The contract should be ready for use immediately after deployment, with the bankBalances value initialized to the provided value.
Observed Behavior
The proxy contract is deployed, but the initialization logic does not execute correctly when passing the initialization data as part of the deployment process.
The workaround of deploying the contract first and then calling the initialize function manually works, but it requires two separate transactions, which is not ideal.
Workaround
As a temporary workaround, I can:
Manually call the initialize function after deployment of the contract
Verify the state of the contract after initialization.
Assign contract to the proxy
However, this workaround is cumbersome and ideally should be done in a single transaction.
Request for Help
This issue might not be a bug, but rather a misunderstanding or a gap in the documentation. I've searched through the documentation and issues but couldn't find a clear solution. Any guidance on why the initialization is failing and how to properly pass initialization data during deployment would be greatly appreciated.
The text was updated successfully, but these errors were encountered:
I'm encountering an issue when using the OpenZeppelin proxy pattern. Specifically, the upgradeToAndCall function in ERC1967Utils.sol fails to correctly initialize my contract using functionDelegateCall.
Problem Description
I am using the following setup:
Contract: TestContractUpgradableV1
upgradeToAndCall Function in ERC1967Utils.sol:
Problem Encountered
When trying to initialize the contract during deployment via the upgradeToAndCall function, the initialization does not work as expected when passing initialization data. Specifically, calling the initialization method during the proxy contract deployment fails to execute.
Java/Web3j Code
The following code attempts to deploy a proxy and initialize the contract:
Generated Deployment Function:
Expected Behavior
The expectation is that the proxy contract should be deployed and initialized in one transaction using the upgradeToAndCall method. The contract should be ready for use immediately after deployment, with the bankBalances value initialized to the provided value.
Observed Behavior
Workaround
As a temporary workaround, I can:
However, this workaround is cumbersome and ideally should be done in a single transaction.
Request for Help
This issue might not be a bug, but rather a misunderstanding or a gap in the documentation. I've searched through the documentation and issues but couldn't find a clear solution. Any guidance on why the initialization is failing and how to properly pass initialization data during deployment would be greatly appreciated.
The text was updated successfully, but these errors were encountered: