EIP-1822: Universal Upgradeable Proxy Standard (UUPS)

To improve compatibility of this proxy with existing and future solutions, I think it would be much better to use the slot defined in EIP-1967: Standard Proxy Storage Slots. @pi0neerpat Can you explain the reasons why this was explicitly decided against? We’re trying to move said EIP to Final state and it would be good to have UUPS on board.

We really do like this model and want to provide an implementation of it in OpenZeppelin Contracts but the choice of an incompatible storage slot sticks out as a problem for us. For inclusion in OpenZeppelin it would also be necessary to move this EIP to Final.

We are on board too with this new 1967 storage slot naming. Working on it here and will report back here once we are finished https://github.com/ethereum/EIPs/pull/2750

1 Like

Currently the purpose of proxiableUUID is not well explained.

It seems to me it would be made more useful, if it would be about differentiating different types of logic contract as opposes to the slot of the implementation:

abstract contract Proxiable {

...
   /**
     * @dev Proxiable UUID marker function.
     *      This would help to avoid wrong logic contract to be used for upgrading.
     */
    function proxiableUUID() public pure virtual returns (bytes32);

    /**
     * @dev Update code address function.
     *      It is internal, so the derived contract could setup its own permission logic.
     */
    function _updateCodeAddress(address newAddress) internal {
        require(
            proxiableUUID() == Proxiable(newAddress).proxiableUUID(),
            "Proxiable: NOT_COMPATIBLE"
        );
        ProxyUtils.setImplementation(newAddress);
...

While in actual implementation of a specific contract:

    function proxiableUUID() public pure override returns (bytes32) {
        return keccak256("org.rdai.contracts.RToken.implementation");
    }

Yes the language here is vague about what the uuid could be intentionally. Would adding some more examples here be helpful? Or would you want to see the section changed to explain more about how uuid should be used?

The code example from the proposal is:

    function updateCodeAddress(address newAddress) internal {
        require(
            bytes32(0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7) == Proxiable(newAddress).proxiableUUID(),
            "Not compatible"
        );

And that is suggesting proxiableUUID is basically the slot ID, which I find un-useful. If I wanted to distinguish different type of logic contract, I would rather use the UUID scheme I proposed in the previous reply. Is that close to what you have had in mind, or I have deviated from the original idea?