How to easily get the ProxyAdmin address of the TransparentUpgradeableProxy (v5)?

We are currently trying to upgrade our contracts to Open Zeppelin V5, but we have two questions concerning the new version of the TransparentUpgradeableProxy:

  1. How can we get the ProxyAdmin address of the TransparentUpgradeableProxy? We need it for upgrades, yet it seems like all getters for it are internal, hence it is hard to get the address (potential solutions which are not great for us: checking emitted events after deployment or using the RPC call as stated by the tip you provide in the ERC1967Utils library). Is there any easier way that we missed?

  2. Since ProxyAdmin is now directly instantiated in the constructor, it is now no longer possible to have 1 ProxyAdmin for different Transparent Proxies. It would seem to us like an undesired property, could you provide more on that matter please?

:computer: Environment

We are using foundry.

  1. If you are using Foundry, you can use a cheatcode to read the storage slot. For example, you can add this function in your Foundry script or test:
import {Vm} from "forge-std/Vm.sol";
import {ERC1967Utils} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Utils.sol";

  function getAdminAddress(address proxy) internal view returns (address) {
    address CHEATCODE_ADDRESS = 0x7109709ECfa91a80626fF3989D68f67F5b1DD12D;

    bytes32 adminSlot = vm.load(proxy, ERC1967Utils.ADMIN_SLOT);
    return address(uint160(uint256(adminSlot)));
  1. This was done to avoid an extra storage read before each call. See discussion in
    If you want 1 proxy admin for different transparent proxies, it is possible to extend TransparentUpgradeableProxy to add back the functionality that you need. However, you may consider a different approach depending on your use case, for example even if there are multiple proxy admins, the proxy admins could all be owned by a single owner (such as a multisig).

That's very clear, thank you very much for taking the time!