Admin's use of AdminUpgradeabilityProxy

Hi.

I notice that AdminUpgradeabilityProxy prevents the admin from interacting with the proxy for non-admin functions:

  /**
   * @dev Only fall back when the sender is not the admin.
   */
  function _willFallback() internal {
    require(msg.sender != _admin(), "Cannot call fallback function from the proxy admin");
    super._willFallback();
  }

Is this require necessary for security reasons? I presume it is only to avoid confusion, and therefore I am free to override _willFallback() to allow admins to use the fallback facility if that’s the behaviour I want?

Thanks.

N

1 Like

Hi @nmclrn,

Can you give a bit more detail on what you want to achieve?

OpenZeppelin SDK uses the transparent proxy pattern.

https://docs.openzeppelin.com/sdk/2.5/pattern#transparent-proxies-and-function-clashes
A transparent proxy will decide which calls are delegated to the underlying logic contract based on the caller address (ie the msg.sender ):

  • If the caller is the admin of the proxy (the address with rights to upgrade the proxy), then the proxy will not delegate any calls, and only answer any messages it understands.
  • If the caller is any other address, the proxy will always delegate a call, no matter if it matches one of the proxy’s functions.

If you are using the OpenZeppelin CLI this creates an intermediary ProxyAdmin contract that is in charge of all the proxies you create via the CLI.

Hi @abcoathup.

Thanks for the reply.

I’m not using the CLI (yet) - I just want to inherit from AdminUpgradabilityProxy to deploy a proxy contract that I can:

  • A upgrade (i.e. point to a new logic contract) using the admin address
  • B use as a proxy contract from all non-admin addresses
  • C use as a proxy contract from the admin address, when calling functions that are not defined on the proxy itself.

AdminUpgradabilityProxy as written gives me A and B, but the highlighted require prevents C.

Put another way, I’m trying to change your first bullet to:

  • If the caller is the admin of the proxy (the address with rights to upgrade the proxy), then the proxy will answer any messages it understands, and will delegate all other calls.

Does that make sense?

Thanks!

N

1 Like

Hi @nmclrn,

I would encourage using OpenZeppelin SDK:

https://docs.openzeppelin.com/sdk/2.5/pattern.html
… the OpenZeppelin SDK is designed to encapsulate all the proxy mechanics in a way that the amount of things you need to keep in mind when developing projects are reduced to an absolute minimum. It all comes down to the following list:

  • Have a basic understanding of what a proxy is
  • Always extend storage instead of modifying it
  • Make sure your contracts use initializer functions instead of constructors

Furthermore, the OpenZeppelin SDK will let you know when something goes wrong with one of the items in this list.

I still don’t understand the why of needing C, wanting the admin for the proxy to also be able to be used for other purposes. Can you provide more details on this?

From a separation of concerns perspective I would just have the proxy admin only be the proxy admin.

If you need access control mechanisms then there are multiple options in https://github.com/OpenZeppelin/openzeppelin-contracts-ethereum-package
See the OpenZeppelin Contracts documentation on Access Control: https://docs.openzeppelin.com/contracts/2.x/access-control

1 Like

Thanks for the reply, @abcoathup!

The why is simply that, for our use case, we want the admin to be able to use the proxy contact like other users can. I won’t bore you with details because this is obviously something we could redesign as you suggest if there were a pressing need to do so (e.g. for security reasons), and we may do so later anyway, but in the short run this approach is more convenient if the “only” reasons to redesign are separation of concerns & avoiding function signature clashes.

Re: using OpenZeppelin SDK, it’s our intention to go that route eventually, if for no other reason than to get the storage layout back-compatibility checks. But it seems non-straightforward because we have the following non-standard requirements:

  • the aforementioned requirement for the admin to have full use of the proxy
  • this is an existing multi-contract system, with numerous truffle migrations that we would rather not re-write
  • we want to change one of the existing contracts to be upgradable, by separating logic from storage, but this contract is deployed by a factory contract (rather on the command line)

I know you have example code that illustrates a system with some of these properties, but moving our system with all of these properties into your SDK seems to involve some effort and risk. (If you disagree, I’d welcome pointers!) Hence this intermediate step.

N

1 Like

Hi @nmclrn,

Thank you for explaining your requirements, that is very helpful to understand.

For the situation of deploying an upgradeable contract via a factory contract I suggest having a look at using a ProxyAdmin (the same as OpenZeppelin SDK does), which will be the actual admin for the proxy contract being created by the factory. This then allows your admin account control of upgrade functionality via ProxyAdmin and fully interact with the proxy contract.

See the documentation for some more information on this:
https://docs.openzeppelin.com/sdk/2.5/pattern.html#transparent-proxies-and-function-clashes

This would allow you to use the OpenZeppelin Upgrades contracts as is.


With regards existing Truffle Migrations, you can also use migrations to deploy OpenZeppelin SDK contracts so if/when you add OpenZeppelin SDK contracts to your system you don’t need to redo all the migrations.