Best practices to write Version 2 contract for upgrade

Hey guys, So my question is let's say I created contract contractA and deployed it using an open zeppelin upgrade. And now I want to upgrade it with contractAVersion2 , So in this new contractAVersion2 I want to override few methods of the first version and also some new methods. So one way I found was to inherit contractA into contractAVersion2 and then override methods or add a new one. But there are few problems that I have:

  1. There are few methods in version1 contract that are not declared virtual and hence I cannot override them.
  2. Super keyword in version 1 points to open zeppelin erc20 contract , but in version2 if I inherit version 1 , super keyword will point to version 1 and not open zeppelin contract sitting on top of inheritence.

So solution I found was rather then inheriting version 1 contract , I will copy the whole code of version 1 in version 2 and then make my changes into it. In this way I won't have to override anything , and super keyword will still point to open zeppelin erc20.

So my question is , is this a fair practice? Or what will be correct practices to create this version 2.

:1234: Code to reproduce


:computer: Environment

Hi, welcome! :wave:

I think when you upgrade a contract with a new implementation, it will use the new logic, so even though it is not a virtual function, you can just re-write it to achieve the new logic.

Not sure what do you mean.

Kind reminder! you can upgrade your contract at any time, but do not change the order of the variable, and you can also have a look at this documentation:

Let me explain it using an example. Let's say my first contract looked like this:

contract contractA{
uint256 public counter;
....
...
function increment() public{
counter+=1;
}
}

Now I have two ways to create version 2 for this in my mind
One way is this as shown below

contract contractAVersion2 is contractA{
function increment() public{
// some new logic
}

}

And then upgrade contractA with this contract but compiler doesn't compile this contract because I can't override increment since it is not virtual.
Or I can simply do this:

contract contractAVersion2{
uint256 public counter;
....
...
function increment() public{
// Some new logic
}
}

And then upgrade it , which seems to work. So the second approach is fine right?

Ohhhh, I see. Yeah, you are right, the second way will work.

Hi! Just a question. I'm kind of new to Solidity and OpenZeppelin. What happens to the old counter variable in storage if you upgrade your contract with the second approach? Also, what if you change the variable names? Will counter variable be deleted?

Hi @lalalei, in the second approach, the counter variable will keep the same state after the upgrade. You can also rename the variable, as long as you don't change its type, because it will continue to occupy the same storage slot. For more examples, see the link in this comment.

1 Like