Upgradable Contract Question

Hello everyone!
We have an upgradeable contract and our state variables are stored in a struct on the storage contract. We are planning to make an upgrade that will require new state variables, which I am planning to add to our struct of variables. So far I've tested it on testnet and haven't found any issues, but are there any problems y'all can think of with doing the upgrade this way?

Thanks!

Hi, can you include a sample contract demonstrating what you are trying to do? Its not clear what you mean by "I am planning to add to our struct of variables.", will you modify a struct or add new state variable of type struct?

Hello! Thank you for your response. So below is our struct called "Layout", the last two variables in that struct were originally not there. Does adding them create any risk of overwriting other data?

library NFTStorage {
    struct Layout {
        // =============================================================
        //                            STORAGE
        // =============================================================
        
        address SALE_ROLE; // EOA or ContractWallet,can set sale price,sale time
        address MINT_ROLE; // EOA only, can sign for special mint
        address SYNTH_ROLE; // EOA only, can sign for NFT synthesis
        string baseURI;

        /**
         * address can claim ETH
         */
        address payable paymentReceiver;
        /**
         * the token stake contract address
         */
        address defalutApproval;
        /**
         * max mint limit, will +1 only after SyntheticMinted
         */
        uint32 mintLimit;
        /**
         * saled count
         */
        uint32 remainingSaleCount;
        /**
         * sale start time
         */
        uint64 saleStartTime;
        /**
         * sale end time
         */
        uint64 saleEndTime;
        /**
         * sale price
         */
        uint256 salePrice;
        /**
         * signature => used
         */
        mapping(bytes32 => bool) mintedSignature;

        // N E W  V A R I A B L E S
        mapping(address => bool) isWhitelisted;

        uint256 wlPrice;
    }

    bytes32 internal constant STORAGE_SLOT =
        keccak256("NFTStorage.location");

    function layout() internal pure returns (Layout storage l) {
        bytes32 slot = STORAGE_SLOT;
        assembly {
            l.slot := slot
        }
    }
}

From this code I assume you didn't have a declared variable under the Layoutstruct type but rather you return it from a function, in that case it shouldn't be a problem, but if you had declared a Layout variable the storage is going to be shifted.

1 Like

Yes we return it from a function.
We do declare this in the beginning of our main logic contract

    using NFTStorage for NFTStorage.Layout;

But I doubt that will have an impact. We're really storing everything in this struct, nothing in our main logic contract.

The using statement doesn't affect storage layout.

If all of your storage is located in the struct, this is fine. If you have multiple structs that you're using separately, or you have other state variables defined outside the struct, we would need to see more details to tell if it would cause issues.

1 Like