@ -1,7 +1,7 @@
/ / SPDX - License - Identifier : MIT
/ / OpenZeppelin Contracts ( last updated v4 . 9 . 0 ) ( proxy / ERC1967 / ERC1967Upgrade . sol )
/ / OpenZeppelin Contracts ( last updated v4 . 9 . 0 ) ( proxy / ERC1967 / ERC1967Utils . sol )
pragma solidity ^ 0 . 8 . 19 ;
pragma solidity ^ 0 . 8 . 20 ;
import " ../beacon/IBeacon.sol " ;
import " ../../interfaces/IERC1967.sol " ;
@ -15,7 +15,24 @@ import "../../utils/StorageSlot.sol";
*
* _Available since v4 . 1 . _
* /
abstract contract ERC1967Upgrade is IERC1967 {
library ERC1967Utils {
/ / We re - declare ERC - 1967 events here because they can ' t be used directly from IERC1967.
/ / This will be fixed in Solidity 0 . 8 . 21 . At that point we should remove these events .
/**
* @ dev Emitted when the implementation is upgraded .
* /
event Upgraded ( address indexed implementation ) ;
/**
* @ dev Emitted when the admin account has changed .
* /
event AdminChanged ( address previousAdmin , address newAdmin ) ;
/**
* @ dev Emitted when the beacon is changed .
* /
event BeaconUpgraded ( address indexed beacon ) ;
/ / This is the keccak - 256 hash of " eip1967.proxy.rollback " subtracted by 1
bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143 ;
@ -24,7 +41,8 @@ abstract contract ERC1967Upgrade is IERC1967 {
* This is the keccak - 256 hash of " eip1967.proxy.implementation " subtracted by 1 , and is
* validated in the constructor .
* /
bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc ;
/ / solhint - disable - next - line private - vars - leading - underscore
bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc ;
/**
* @ dev The ` implementation ` of the proxy is invalid .
@ -49,8 +67,8 @@ abstract contract ERC1967Upgrade is IERC1967 {
/**
* @ dev Returns the current implementation address .
* /
function _ getImplementation( ) internal view returns ( address ) {
return StorageSlot . getAddressSlot ( _ IMPLEMENTATION_SLOT) . value ;
function getImplementation ( ) internal view returns ( address ) {
return StorageSlot . getAddressSlot ( IMPLEMENTATION_SLOT ) . value ;
}
/**
@ -60,15 +78,15 @@ abstract contract ERC1967Upgrade is IERC1967 {
if ( newImplementation . code . length == 0 ) {
revert ERC1967InvalidImplementation ( newImplementation ) ;
}
StorageSlot . getAddressSlot ( _ IMPLEMENTATION_SLOT) . value = newImplementation ;
StorageSlot . getAddressSlot ( IMPLEMENTATION_SLOT ) . value = newImplementation ;
}
/**
* @ dev Perform implementation upgrade
*
* Emits an { Upgraded } event .
* Emits an { IERC1967 - Upgraded } event .
* /
function _ upgradeTo( address newImplementation ) internal {
function upgradeTo ( address newImplementation ) internal {
_setImplementation ( newImplementation ) ;
emit Upgraded ( newImplementation ) ;
}
@ -76,10 +94,10 @@ abstract contract ERC1967Upgrade is IERC1967 {
/**
* @ dev Perform implementation upgrade with additional setup call .
*
* Emits an { Upgraded } event .
* Emits an { IERC1967 - Upgraded } event .
* /
function _ upgradeToAndCall( address newImplementation , bytes memory data , bool forceCall ) internal {
_ upgradeTo( newImplementation ) ;
function upgradeToAndCall ( address newImplementation , bytes memory data , bool forceCall ) internal {
upgradeTo ( newImplementation ) ;
if ( data . length > 0 || forceCall ) {
Address . functionDelegateCall ( newImplementation , data ) ;
}
@ -88,9 +106,9 @@ abstract contract ERC1967Upgrade is IERC1967 {
/**
* @ dev Perform implementation upgrade with security checks for UUPS proxies , and additional setup call .
*
* Emits an { Upgraded } event .
* Emits an { IERC1967 - Upgraded } event .
* /
function _ upgradeToAndCallUUPS( address newImplementation , bytes memory data , bool forceCall ) internal {
function upgradeToAndCallUUPS ( address newImplementation , bytes memory data , bool forceCall ) internal {
/ / Upgrades from old implementations will perform a rollback test . This test requires the new
/ / implementation to upgrade back to the old , non - ERC1822 compliant , implementation . Removing
/ / this special case will break upgrade paths from old UUPS implementation to new ones .
@ -98,14 +116,14 @@ abstract contract ERC1967Upgrade is IERC1967 {
_setImplementation ( newImplementation ) ;
} else {
try IERC1822Proxiable ( newImplementation ) . proxiableUUID ( ) returns ( bytes32 slot ) {
if ( slot != _ IMPLEMENTATION_SLOT) {
if ( slot != IMPLEMENTATION_SLOT ) {
revert ERC1967UnsupportedProxiableUUID ( slot ) ;
}
} catch {
/ / The implementation is not UUPS
revert ERC1967InvalidImplementation ( newImplementation ) ;
}
_ upgradeToAndCall( newImplementation , data , forceCall ) ;
upgradeToAndCall ( newImplementation , data , forceCall ) ;
}
}
@ -114,7 +132,8 @@ abstract contract ERC1967Upgrade is IERC1967 {
* This is the keccak - 256 hash of " eip1967.proxy.admin " subtracted by 1 , and is
* validated in the constructor .
* /
bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103 ;
/ / solhint - disable - next - line private - vars - leading - underscore
bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103 ;
/**
* @ dev Returns the current admin .
@ -123,8 +142,8 @@ abstract contract ERC1967Upgrade is IERC1967 {
* https : / / eth . wiki / json - rpc / API # eth_getstorageat [ ` eth_getStorageAt ` ] RPC call .
* ` 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103 `
* /
function _ getAdmin( ) internal view returns ( address ) {
return StorageSlot . getAddressSlot ( _ ADMIN_SLOT) . value ;
function getAdmin ( ) internal view returns ( address ) {
return StorageSlot . getAddressSlot ( ADMIN_SLOT ) . value ;
}
/**
@ -134,30 +153,31 @@ abstract contract ERC1967Upgrade is IERC1967 {
if ( newAdmin == address ( 0 ) ) {
revert ERC1967InvalidAdmin ( address ( 0 ) ) ;
}
StorageSlot . getAddressSlot ( _ ADMIN_SLOT) . value = newAdmin ;
StorageSlot . getAddressSlot ( ADMIN_SLOT ) . value = newAdmin ;
}
/**
* @ dev Changes the admin of the proxy .
*
* Emits an { AdminChanged } event .
* Emits an { IERC1967 - AdminChanged } event .
* /
function _ changeAdmin( address newAdmin ) internal {
emit AdminChanged ( _ getAdmin( ) , newAdmin ) ;
function changeAdmin ( address newAdmin ) internal {
emit AdminChanged ( getAdmin ( ) , newAdmin ) ;
_setAdmin ( newAdmin ) ;
}
/**
* @ dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy .
* This is bytes32 ( uint256 ( keccak256 ( ' eip1967.proxy.beacon ' ) ) - 1 ) ) and is validated in the constructor .
* This is bytes32 ( uint256 ( keccak256 ( ' eip1967.proxy.beacon ' ) ) - 1 ) and is validated in the constructor .
* /
bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50 ;
/ / solhint - disable - next - line private - vars - leading - underscore
bytes32 internal constant BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50 ;
/**
* @ dev Returns the current beacon .
* /
function _ getBeacon( ) internal view returns ( address ) {
return StorageSlot . getAddressSlot ( _ BEACON_SLOT) . value ;
function getBeacon ( ) internal view returns ( address ) {
return StorageSlot . getAddressSlot ( BEACON_SLOT ) . value ;
}
/**
@ -173,16 +193,16 @@ abstract contract ERC1967Upgrade is IERC1967 {
revert ERC1967InvalidImplementation ( beaconImplementation ) ;
}
StorageSlot . getAddressSlot ( _ BEACON_SLOT) . value = newBeacon ;
StorageSlot . getAddressSlot ( BEACON_SLOT ) . value = newBeacon ;
}
/**
* @ dev Perform beacon upgrade with additional setup call . Note : This upgrades the address of the beacon , it does
* not upgrade the implementation contained in the beacon ( see { UpgradeableBeacon - _setImplementation } for that ) .
*
* Emits a { BeaconUpgraded } event .
* Emits an { IERC1967 - BeaconUpgraded } event .
* /
function _ upgradeBeaconToAndCall( address newBeacon , bytes memory data , bool forceCall ) internal {
function upgradeBeaconToAndCall ( address newBeacon , bytes memory data , bool forceCall ) internal {
_setBeacon ( newBeacon ) ;
emit BeaconUpgraded ( newBeacon ) ;
if ( data . length > 0 || forceCall ) {