Skip to content

Commit

Permalink
refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
Amxx committed Mar 9, 2021
1 parent f4d225d commit 1e133ae
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 81 deletions.
4 changes: 2 additions & 2 deletions contracts/proxy/ERC1967/ERC1967Proxy.sol
Expand Up @@ -2,7 +2,7 @@

pragma solidity ^0.8.0;

import "./ERC1967Utils.sol";
import "./ERC1967Storage.sol";
import "../Proxy.sol";
import "../../utils/Address.sol";

Expand All @@ -15,7 +15,7 @@ import "../../utils/Address.sol";
* Upgradeability is only provided internally through {_upgradeTo}. For an externally upgradeable proxy see
* {TransparentUpgradeableProxy}.
*/
contract ERC1967Proxy is Proxy, ERC1967Utils {
contract ERC1967Proxy is Proxy, ERC1967Storage {
/**
* @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.
*
Expand Down
Expand Up @@ -6,7 +6,7 @@ import "../beacon/IBeacon.sol";
import "../../utils/Address.sol";
import "../../utils/StorageSlot.sol";

abstract contract ERC1967ImplementationUtils {
abstract contract ERC1967Storage {
/**
* @dev Storage slot with the address of the current implementation.
* This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is
Expand All @@ -17,15 +17,10 @@ abstract contract ERC1967ImplementationUtils {
// This is the keccak-256 hash of "eip1967.proxy.upgradePending" subtracted by 1
bytes32 internal constant _UPGRADE_PENDING_SLOT = 0x39c07022fef61edd40345eccc814df883dce06b1b65a92ff48ae275074d292ee;

/**
* @dev Emitted when the implementation is upgraded.
*/
event Upgraded(address indexed implementation);

/**
* @dev Returns the current implementation address.
*/
function _getImplementation() internal view virtual returns (address) {
function _getImplementation() internal view returns (address) {
return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
}

Expand All @@ -37,25 +32,30 @@ abstract contract ERC1967ImplementationUtils {
StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
}

/**
* @dev Emitted when the implementation is upgraded.
*/
event Upgraded(address indexed implementation);

/**
* @dev Perform implementation upgrade (with additional setup call)
*
* Emits an {Upgraded} event.
*/
function _upgradeToAndCall(address newImplementation, bytes memory data) internal virtual {
function _upgradeToAndCall(address newImplementation, bytes memory data) internal {
_setImplementation(newImplementation);
emit Upgraded(newImplementation);
if (data.length > 0) {
Address.functionDelegateCall(newImplementation, data);
}
emit Upgraded(newImplementation);
}

/**
* @dev Perform implementation upgrade (with security checks and additional setup call)
*
* Emits an {Upgraded} event.
*/
function _upgradeToAndCallSecure(address newImplementation, bytes memory data) internal virtual {
function _upgradeToAndCallSecure(address newImplementation, bytes memory data) internal {
address oldImplementation = _getImplementation();
// check if nested in an upgrade check
StorageSlot.BooleanSlot storage upgradePending = StorageSlot.getBooleanSlot(_UPGRADE_PENDING_SLOT);
Expand Down Expand Up @@ -85,63 +85,35 @@ abstract contract ERC1967ImplementationUtils {
emit Upgraded(newImplementation);
}
}
}

abstract contract ERC1967AdminUtils {
/**
* @dev Storage slot with the admin of the contract.
* 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;

/**
* @dev Emitted when the admin account has changed.
*/
event AdminChanged(address previousAdmin, address newAdmin);

/**
* @dev Returns the current admin.
*/
function _getAdmin() internal view virtual returns (address) {
return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;
}

/**
* @dev Stores a new address in the EIP1967 admin slot.
* @dev Emitted when the beacon is upgraded.
*/
function _setAdmin(address newAdmin) private {
require(newAdmin != address(0), "ERC1967: new admin is the zero address");
StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;
}
event BeaconUpgraded(address indexed beacon);

/**
* @dev Changes the admin of the proxy.
* @dev Perform implementation upgrade (with addition delegate call)
*
* Emits an {AdminChanged} event.
* Emits an {Upgraded} event.
*/
function _changeAdmin(address newAdmin) internal {
emit AdminChanged(_getAdmin(), newAdmin);
_setAdmin(newAdmin);
function _upgradeBeaconToAndCall(address newBeacon, bytes memory data) internal {
_setBeacon(newBeacon);
emit BeaconUpgraded(newBeacon);
if (data.length > 0) {
Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);
}
}
}

abstract contract ERC1967BeaconUtils {
/**
* @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.
*/
bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;

/**
* @dev Emitted when the beacon is upgraded.
*/
event BeaconUpgraded(address indexed beacon);

/**
* @dev Returns the current beacon.
*/
function _getBeacon() internal view virtual returns (address) {
function _getBeacon() internal view returns (address) {
return StorageSlot.getAddressSlot(_BEACON_SLOT).value;
}

Expand All @@ -161,28 +133,39 @@ abstract contract ERC1967BeaconUtils {
}

/**
* @dev Perform implementation upgrade
*
* Emits an {Upgraded} event.
* @dev Storage slot with the admin of the contract.
* This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is
* validated in the constructor.
*/
function _upgradeBeaconTo(address newBeacon) internal virtual {
_upgradeBeaconToAndCall(newBeacon, bytes(""));
bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;

/**
* @dev Returns the current admin.
*/
function _getAdmin() internal view returns (address) {
return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;
}

/**
* @dev Perform implementation upgrade (with addition delegate call)
* @dev Stores a new address in the EIP1967 admin slot.
*/
function _setAdmin(address newAdmin) private {
require(newAdmin != address(0), "ERC1967: new admin is the zero address");
StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;
}

/**
* @dev Emitted when the admin account has changed.
*/
event AdminChanged(address previousAdmin, address newAdmin);

/**
* @dev Changes the admin of the proxy.
*
* Emits an {Upgraded} event.
* Emits an {AdminChanged} event.
*/
function _upgradeBeaconToAndCall(address newBeacon, bytes memory data) internal virtual {
// TODO: additional security checks ?
_setBeacon(newBeacon);
// TODO: change event to match AdminChanged ?
emit BeaconUpgraded(newBeacon);
if (data.length > 0) {
Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);
}
function _changeAdmin(address newAdmin) internal {
emit AdminChanged(_getAdmin(), newAdmin);
_setAdmin(newAdmin);
}
}

abstract contract ERC1967Utils is ERC1967ImplementationUtils, ERC1967AdminUtils, ERC1967BeaconUtils {}
4 changes: 2 additions & 2 deletions contracts/proxy/ERC1967/ERC1967Upgrade.sol
Expand Up @@ -2,9 +2,9 @@

pragma solidity ^0.8.0;

import "./ERC1967Utils.sol";
import "./ERC1967Storage.sol";

abstract contract ERC1967Upgrade is ERC1967Utils {
abstract contract ERC1967Upgrade is ERC1967Storage {
/**
* @dev Upgrade the implementation of the proxy.
*/
Expand Down
2 changes: 1 addition & 1 deletion contracts/proxy/ERC1967/ERC1967UpgradeSecure.sol
Expand Up @@ -12,6 +12,6 @@ abstract contract ERC1967UpgradeSecure is ERC1967Upgrade {
*/
function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual override {
beforeUpgrade(newImplementation);
_upgradeToAndCallSecure(newImplementation, data);
ERC1967Storage._upgradeToAndCallSecure(newImplementation, data);
}
}
4 changes: 2 additions & 2 deletions contracts/proxy/beacon/BeaconProxy.sol
Expand Up @@ -4,7 +4,7 @@ pragma solidity ^0.8.0;

import "./IBeacon.sol";
import "../Proxy.sol";
import "../ERC1967/ERC1967Utils.sol";
import "../ERC1967/ERC1967Storage.sol";

/**
* @dev This contract implements a proxy that gets the implementation address for each call from a {UpgradeableBeacon}.
Expand All @@ -14,7 +14,7 @@ import "../ERC1967/ERC1967Utils.sol";
*
* _Available since v3.4._
*/
contract BeaconProxy is Proxy, ERC1967Utils {
contract BeaconProxy is Proxy, ERC1967Storage {
/**
* @dev Initializes the proxy with `beacon`.
*
Expand Down
9 changes: 1 addition & 8 deletions contracts/proxy/transparent/TransparentUpgradeableProxy.sol
Expand Up @@ -70,14 +70,7 @@ contract TransparentUpgradeableProxy is ERC1967Proxy, ERC1967Upgrade {
* `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`
*/
function implementation() external ifAdmin returns (address implementation_) {
implementation_ = _getImplementation();
}

/**
* @dev Returns the current implementation address.
*/
function _implementation() internal view virtual override returns (address) {
return _getImplementation();
return _implementation();
}

/**
Expand Down

0 comments on commit 1e133ae

Please sign in to comment.