Help me understand how this upgradeable contract's initialize() works?

I am looking at this AdminUpgradeabilityProxy contract: https://bscscan.com/address/0x8cb88701790f650f273c8bb2cc4c5f439cd65219#code

and find that this proxy’s implementation contract’s initialize() function is:

contract BunnyMinterV2 is IBunnyMinterV2, OwnableUpgradeable {
    ...
    function initialize() external initializer {
        WITHDRAWAL_FEE_FREE_PERIOD = 3 days;
        WITHDRAWAL_FEE = 50;
        PERFORMANCE_FEE = 3000;

        bunnyPerProfitBNB = 5e18;
        bunnyPerBunnyBNBFlip = 6e18;

        IBEP20(BUNNY).approve(BUNNY_POOL, uint(- 1));
    }
    ...
}

I notice there is no owner set in this initialize() function, but by checking the events of this contract creation transaction, I see 2 events:

  1. one is the Approval event, it is what the initializer does
  2. the other is OwnershipTransferred(address,address) ( keccak hash is 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0), I wonder where is this event coming from.

According to my understanding, in order to set owner, we have to call Ownable.initialize(sender); explicitly in the initializer, so how is this owner set?

I have tried to deploy the contract on testnet, and the owner is not set in my deployment, so I wonder how the contract creation transaction I posted above managed to get the owner set.

contract and tx info:

Perhaps it’s in the contract OwnableUpgradeable where the owner is set? The owner is set before the BunnyMinterV2 contract is called.

1 Like

thanks for your reply, it is very likely so since the OwnershipTransferred event happened before the Approval event.

While do you have any idea how can I re-produce this?

I would recreate it exactly as they have it on the mainnet, but using rinkeby instead.