Make TransparentUpgradeableProxy deploy its ProxyAdmin and optimize proxy interfaces by ernestognw · Pull Request #4382 · OpenZeppelin/openzeppelin-contracts (original) (raw)

We are able to optimize TransparentUpgradeableProxy by removing upgradeToAndCall, because it will always be attached to a ProxyAdmin which can just use upgradeTo and separately call a function atomically. This is the "reduced" interface measured in the table below.

We make TransparentUpgradeableProxy deploy a ProxyAdmin in its constructor. This is the "embedded" version below. I tried a few variations to see whether making ProxyAdmin attached to a single proxy improves cost, these are the "1:1" variations.

These are the measured deployment costs. Note that the total for non-embedded is the sum of admin + proxy. But when embedded, the total is just the proxy.

ProxyAdmin TransparentUpgradeableProxy total
baseline (4.9) 443289 630553 1073842
baseline (master) 321406 445272 766678
reduced 366449 298173 664622
reduced + embedded + 1:1 (storage) 376956 655177 655177
reduced + embedded 366449 644874 644874
reduced + embedded + 1:1 (immutable) 364405 642642 642642

The cheapest version we get is 1:1 using an immutable variable. In this case, the upgrade functions don't have a proxy argument, because the proxy is kept in a contract variable. Note that this changes the interface and we have a similar problem in Upgrades Plugins than what we've discussed before: how do the plugins know which function to call? Unless we add some way to inspect the ProxyAdmin version, we don't know. At least in the case of changing the function signatures it would fail.

There is one option that is cheaper which is removing upgradeTo from ProxyAdmin and making upgradeToAndCall skip the call if data is empty. In this case we can get the cost down to 618300 (or 629536 for 1:1 variation). This one is problematic because it makes it hard for tooling like Upgrades Plugins to know which function to call for an upgrade. Depending on the version one function may not be available, and the other behaves different in each version.

I slightly lean towards reduced + embedded in the table above, because I feel there is some risk that a ProxyAdmin could be reused for multiple proxies and break with the 1:1 variation. This is the version in the PR currently.