How can base contracts have the same variable

Hi OpenZeppelin,

I'd love to get your point of view on this. This is mostly not related to OpenZeppelin, but would appreciate your inputs about how you solve problems like mine. Derived class inherits from UUPSUpgradable.

I have 2 base contracts.

contract Base1 {
   
   function nice1() public {

   }
 
}

contract Base2 {
   
   function nice2() public {

   }
 
}

contract Derived is Base1, Base2 {
   
   function initialize(addres _sender) public {

   }
 
}

Like nice1 and nice2, there're other functions in base contracts as well. I need _sender to be available in mostly all functions of Base1 and Base2.

I am thinking how I can achieve this ?

Way 1: Base1 has a state variable called _sender and also a function initialize and I call this function from Derived. Same goes for Base2, but now, I won't be able to have _sender as name clashes would happen in Derived in the end. so I bring _sender2 as the state variable and bring initialize in Base2 and set it. This is a bad way, as the same variable will be defined in Derived 2 times.

Way 2: One way I could think of is in the Derived' initialize, I put _sender in the specific slot (keccak256('_sender_slot')) and since base contracts are in the end put in the Derived, base contract's functions can simply read _sender_slot and get the value.

Way 3: having an interface such as abstract contract Storage { address public _sender; }. I set _sender in Derived , and Base1 and Base2 extend from Storage which means now they can see _sender.

WDYT from your point of view ? which one seems reasonable and good way ?

When you have a situation like this, option 3 is generally the best solution. Having a common parent where the data is kept.

There is a fourth option that you didn't mention. You can make Base1 and Base2 have an abstract function getSender, and have Derived store the sender value and override that function to return it.