Hi @angryetherpotamus, thanks for the detailed and well described questions
Here are my responses:
- I would expect
owner()
and_owner
at the logic address to be 0, because the logic contract itself is not initialized so the default value of the_owner
variable is the 0 address. Are you using OpenZeppelin Contracts v5? For example, see https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/v5.0.2/contracts/access/OwnableUpgradeable.sol -- there is no constructor for the upgradeable variant, and the initializer is disabled (as you correctly did using_disableInitializers
) for the logic contract itself. - It is not recommended to add public functions in the proxy, due to possible function selector clashes between the proxy and logic contract. See https://blog.nomic.foundation/malicious-backdoors-in-ethereum-proxies-62629adf3357 for a detailed explanation.
Usually, you should not need to reimplement a proxy contract. You can just deploy one of the proxy contracts from OpenZeppelin Contracts directly, such as ERC1967Proxy.
You can read the storage slot to get the address, for example by using tools such as Upgrades Plugins. - The implementation contract itself shouldn't need to be paused, because it is expected to be disabled from initialization and therefore stateless. See What does `_disableInitializers();` function mean? - #2 by ericglau. Even if you initialized it, the state of the implementation contract would be unrelated to the states of the proxies! (For example, the
_paused
boolean's state is not synchronized between the implementation and proxy).
To do what you described, you would need to explore a different pattern. - Mainly addressed in my other points above, but let me know if you have further questions.