Hello,
I have a quick question. Can i change a private variable to public when upgrading a contract?
Hello,
I have a quick question. Can i change a private variable to public when upgrading a contract?
Hey, happy new year!
Yes, I think so, maybe later I can have a test to confirm.
Cause I think all variables in the contract can be got, just with different levels of difficulty. For public
and external
, you can get them from the contract directly, but for the private
and internal
, you should use another way, such as by the method web3.eth.getStorageAt in the web3.js
Hi @Dellybro,
I assume visibility has no impact on how state variables are stored. As long as you are not changing type or order of state variables this should be fine, though I recommend (as @Skyge said) trying it out yourself.
@skyge do you think the same would be for adding “override”?
Could you please show your code?
Hi @Dellybro,
The keyword override
applies to functions, and not state variables: https://docs.soliditylang.org/en/v0.8.0/contracts.html?highlight=override#function-overriding
So we are using this variable in another contract, so we use the override keyword so it “implements” it’s interface
https://docs.soliditylang.org/en/v0.5.3/contracts.html#visibility-and-getters
Hi @Dellybro,
I am still not sure what you mean. Can you give a simple example. Something like the following?
// contracts/A.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.5.0;
contract A {
uint256 public value;
}
// contracts/B.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.5.0;
import "./A.sol";
contract B is A {
uint256 public value;
}
Hi @Dellybro,
Is this what you were referring to: Is public state var auto getter override upgrade safe? - #2 by Skyge
I have a similar cuestion using OwnedUpgradeabilityProxy:
Lets say I have this contract:
// SPDX-License-Identifier: MIT
pragma solidity >=0.7.0 <0.8.0;
contract ERC721V1_0 {
// Mapping from token ID to owner
mapping (uint256 => address) internal _tokenOwner;
//upgradability
bool internal _initialized;
function initialize() public {
require(!_initialized, "Contract already initialized");
_initialized = true;
}
function ownerOf(uint256 tokenId) internal view returns (address) {
address owner = _tokenOwner[tokenId];
require(owner != address(0), "ERC721: owner query for nonexistent token");
return owner;
}
}
Once deployed, I want to change the function visibility to external, so I go to the same ERC721V1_0
contract and change the function to (please note that the function name now changed from ownerOf to _ownerOf
:
function _ownerOf(uint256 tokenId) internal view returns (address) {
address owner = _tokenOwner[tokenId];
require(owner != address(0), "ERC721: owner query for nonexistent token");
return owner;
}
Then I create a new contract which will upgrade the latest:
// SPDX-License-Identifier: MIT
pragma solidity >=0.7.0 <0.8.0;
import "./ERC721V1_0.sol";
contract ERC721V1_1 is ERC721V1_0 {
//upgradability
bool internal _initializedV11;
function initializeV11() public {
require(!_initializedV11, "contract already upgraded");
_initializedV11 = true;
}
function ownerOf(uint256 tokenId) external virtual view returns (address) {
return _ownerOf(tokenId);
}
}
Is this a way to go? I checked some values and it seems to be working but not sure in the long term if the storage somehow will get corrupted