in the constructor of the v5 TransparentUpgradableProxy a new ProxyAdmin contract is created that is accessible through the private variable _admin.
my understanding is that it is this ProxyAdmin contract that is supposed to be used to upgrade the implemented logic of a upgradable contract.
now to my question: what is the recommended way to interact with the ProxyAdmin as the TransparentUpgradableProxy doesn't provide external access to the proxy admin contract?
my current workaround is to extend TransparentUpgradableProxy with a getProxyAdmin function.
however, the documentation says that TransparentUpgradableProxy shouldn't be extended.
additional side question: why is _proxyAdmin() not a view function? at least the current implementation would suggest this is not changing any state variables of TransparentUpgradableProxy .
Generally TransparentUpgradeableProxy should not be extended and does not provide any externally accessible functions (other than admin related functions, which are only callable by the admin) specifically because of the transparent aspect, as described in the TransparentUpgradeableProxy documentation. Any exposed functions in the proxy would have a risk of selector clashing with the implementation.
follow-up question: why is function _proxyAdmin() internal and not public? seems a bit like putting an unnecessary burden on the user to go and obtained the address via event as you suggest above. as the return value is implemented as immutable i can't see any bad side effects from changing the visibility to public. or am i missing something here?
When you call a function which does not exist in the Proxy contract, execution falls into the fallback function, which then calls that function in the Logic contract.
When you call a function which DOES exist in the Proxy contract, it is executed immediately.
So every public or external function that you implement in the Proxy contract, is a function signature (name and input argument types) which you CANNOT implement in the Logic contract.
Hence you'd want to implement as little as possible in the Proxy contract.
I'm not familiar with the V5 change that you've mentioned about upgradeTo being replaced with upgradeToAndCall, but I'd imagine that the same concept applies for the new function, i.e., you should call it using the Proxy-Admin account, similarly to what I showed in the pseudocode above.
As I had very similar comments and questions as the ones brought up by Matthias_Zimmermann, I am wondering if you could elaborate a bit more on the solution that you provided. Indeed, in practice, in a foundry test execution, how can you read an ERC-1967 admin slot of a trusted implementation that was deployed during that execution?
Thanks in advance for your time and consideration.
N.B: I created a similar ticket here, which also addresses another (related) question.
EDIT: I was thinking that maybe the solution brought up by Matthias: an extension of the TransparentUpgradableProxy contract containing a public getter for the admin could be suited to a testing environment? Or is there any arguments against it that would make it a bad idea?