UPUPSUpgradeable
Inherits: UUPSUpgradeable
Title: Universal Proposeable Upgradeable Proxy Standard (UPUPS)
Extends UUPSUpgradeable with a two-step upgrade process that
prevents silent simulated upgrades that could extract confidential contract
state. The upgrader must first call proposeUpgrade to announce the new
implementation, and then call regular upgradeToAndCall in a later block.
Example
contract MyContract is UPUPSUpgradeable, OwnableUpgradeable {
constructor() {
_disableInitializers();
}
function initialize(address _owner) public initializer {
__Ownable_init(_owner);
__UPUPSUpgradeable_init();
}
// Gate _authorizeProposeUpgrade with appropriate modifier.
function _authorizeProposeUpgrade(address, uint256) internal override onlyOwner {}
// Gate UUPSUpgradeable._authorizeUpgrade with appropriate modifier as you normally do.
function _authorizeUpgrade(address) internal override onlyOwner {}
}
Constants
UPUPSUpgradeableStorageLocation
bytes32 private constant UPUPSUpgradeableStorageLocation =
0x2ba9668233a4827367587178d890a758d4583dfd9e5c9ef8b58defb278a6ad00
Functions
_getUPUPSUpgradeableStorage
function _getUPUPSUpgradeableStorage() private pure returns (UPUPSUpgradeableStorage storage $);
__UPUPSUpgradeable_init
function __UPUPSUpgradeable_init() internal onlyInitializing;
__UPUPSUpgradeable_init_unchained
function __UPUPSUpgradeable_init_unchained() internal onlyInitializing;
_authorizeProposeUpgrade
This function should revert when msg.sender is not authorized
to propose the upgrade. Called by proposeUpgrade.
Normally, this function will use an access control modifier such as
Ownable.onlyOwner.
function _authorizeProposeUpgrade(address, uint256) internal onlyOwner {}
function _authorizeProposeUpgrade(address newImplementation, uint256 minBlockNumber) internal virtual;
proposedUpgradeImplementation
Returns the new implementation address of the proposed upgrade.
function proposedUpgradeImplementation() public view returns (address);
proposedUpgradeImplementationHash
Returns the hash of the implementation runtime code of the proposed upgrade.
function proposedUpgradeImplementationHash() public view returns (bytes32);
proposedUpgradeMinBlockNumber
Returns the proposed upgrade minimum block number.
function proposedUpgradeMinBlockNumber() public view returns (uint256);
_acceptProposedUpgrade
Checks that the implementations match and the current block number is at least minBlockNumber. Then consumes the proposed upgrade.
function _acceptProposedUpgrade(address newImplementation) internal virtual;
proposeUpgrade
Propose the upgrade to the new implementation address after the given block number. If minBlockNumber is zero, take the number of the next block.
minBlockNumber is intentionally left to the caller’s discretion: the function guards against the simulated upgrade attack, but a longer upgrade window may be enforced.
function proposeUpgrade(address newImplementation, uint256 minBlockNumber) public virtual onlyProxy;
upgradeToAndCall
Upgrades the proxy to newImplementation, enforcing that it
matches a previously proposed and matured upgrade.
The proposal check is applied here so that overriding
UUPSUpgradeable._authorizeUpgrade can never accidentally skip it.
function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual override onlyProxy;
Events
UpgradeProposed
event UpgradeProposed(
address indexed newImplementation, bytes32 indexed newImplementationHash, uint256 indexed minBlockNumber
);
UpgradeAccepted
event UpgradeAccepted(
address indexed newImplementation, bytes32 indexed newImplementationHash, uint256 indexed minBlockNumber
);
Errors
ImplementationDoesNotMatch
error ImplementationDoesNotMatch();
ImplementationHashDoesNotMatch
error ImplementationHashDoesNotMatch();
MinBlockNumberInPast
error MinBlockNumberInPast();
MinBlockNumberNotReached
error MinBlockNumberNotReached();
NewImplementationNotAContract
error NewImplementationNotAContract();
Structs
UPUPSUpgradeableStorage
Note: storage-location: erc7201:oasisprotocol.storage.UPUPSUpgradeable
struct UPUPSUpgradeableStorage {
address _newImplementation;
bytes32 _newImplementationHash;
uint256 _minBlockNumber;
}