Upgrade safe to change state variable from private to public?

Hello,

I have a quick question. Can i change a private variable to public when upgrading a contract?

1 Like

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

2 Likes

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.

1 Like

@skyge do you think the same would be for adding “override”?

1 Like

Could you please show your code?

1 Like

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

1 Like

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

1 Like

Hi @Dellybro,

I am still not sure what you mean. Can you give a simple example. Something like the following?

A.sol

// contracts/A.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.5.0;

contract A {
    uint256 public value;    
}

B.sol

// 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