diff --git a/contracts/configuration/LendingPoolAddressesProvider.sol b/contracts/configuration/LendingPoolAddressesProvider.sol index 90fe8555..fed14236 100644 --- a/contracts/configuration/LendingPoolAddressesProvider.sol +++ b/contracts/configuration/LendingPoolAddressesProvider.sol @@ -3,8 +3,8 @@ pragma solidity ^0.6.8; import {Ownable} from '@openzeppelin/contracts/access/Ownable.sol'; import { - InitializableAdminUpgradeabilityProxy -} from '../libraries/openzeppelin-upgradeability/InitializableAdminUpgradeabilityProxy.sol'; + InitializableImmutableAdminUpgradeabilityProxy +} from '../libraries/aave-upgradeability/InitializableImmutableAdminUpgradeabilityProxy.sol'; import {ILendingPoolAddressesProvider} from '../interfaces/ILendingPoolAddressesProvider.sol'; @@ -153,14 +153,14 @@ contract LendingPoolAddressesProvider is Ownable, ILendingPoolAddressesProvider function _updateImpl(bytes32 id, address newAddress) internal { address payable proxyAddress = payable(_addresses[id]); - InitializableAdminUpgradeabilityProxy proxy = InitializableAdminUpgradeabilityProxy( + InitializableImmutableAdminUpgradeabilityProxy proxy = InitializableImmutableAdminUpgradeabilityProxy( proxyAddress ); bytes memory params = abi.encodeWithSignature('initialize(address)', address(this)); if (proxyAddress == address(0)) { - proxy = new InitializableAdminUpgradeabilityProxy(); - proxy.initialize(newAddress, address(this), params); + proxy = new InitializableImmutableAdminUpgradeabilityProxy(address(this)); + proxy.initialize(newAddress, params); _addresses[id] = address(proxy); emit ProxyCreated(id, address(proxy)); } else { diff --git a/contracts/lendingpool/LendingPoolConfigurator.sol b/contracts/lendingpool/LendingPoolConfigurator.sol index 3f8643ee..cd64e586 100644 --- a/contracts/lendingpool/LendingPoolConfigurator.sol +++ b/contracts/lendingpool/LendingPoolConfigurator.sol @@ -7,8 +7,8 @@ import { VersionedInitializable } from '../libraries/openzeppelin-upgradeability/VersionedInitializable.sol'; import { - InitializableAdminUpgradeabilityProxy -} from '../libraries/openzeppelin-upgradeability/InitializableAdminUpgradeabilityProxy.sol'; + InitializableImmutableAdminUpgradeabilityProxy +} from '../libraries/aave-upgradeability/InitializableImmutableAdminUpgradeabilityProxy.sol'; import {ReserveConfiguration} from '../libraries/configuration/ReserveConfiguration.sol'; import {ILendingPoolAddressesProvider} from '../interfaces/ILendingPoolAddressesProvider.sol'; import {ILendingPool} from '../interfaces/ILendingPool.sol'; @@ -558,7 +558,9 @@ contract LendingPoolConfigurator is VersionedInitializable { * @param decimals the decimals of the token **/ function _initTokenWithProxy(address implementation, uint8 decimals) internal returns (address) { - InitializableAdminUpgradeabilityProxy proxy = new InitializableAdminUpgradeabilityProxy(); + + InitializableImmutableAdminUpgradeabilityProxy proxy + = new InitializableImmutableAdminUpgradeabilityProxy(address(this)); bytes memory params = abi.encodeWithSignature( 'initialize(uint8,string,string)', @@ -567,7 +569,7 @@ contract LendingPoolConfigurator is VersionedInitializable { IERC20Detailed(implementation).symbol() ); - proxy.initialize(implementation, address(this), params); + proxy.initialize(implementation, params); return address(proxy); } @@ -577,9 +579,9 @@ contract LendingPoolConfigurator is VersionedInitializable { address proxyAddress, address implementation ) internal { - InitializableAdminUpgradeabilityProxy proxy = InitializableAdminUpgradeabilityProxy( - payable(proxyAddress) - ); + + InitializableImmutableAdminUpgradeabilityProxy proxy + = InitializableImmutableAdminUpgradeabilityProxy(payable(proxyAddress)); (uint256 decimals, , , , , , , , , , ) = pool.getReserveConfigurationData(asset); diff --git a/contracts/libraries/aave-upgradeability/BaseImmutableAdminUpgradeabilityProxy.sol b/contracts/libraries/aave-upgradeability/BaseImmutableAdminUpgradeabilityProxy.sol new file mode 100644 index 00000000..05a94805 --- /dev/null +++ b/contracts/libraries/aave-upgradeability/BaseImmutableAdminUpgradeabilityProxy.sol @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: agpl-3.0 +pragma solidity ^0.6.8; + +import '../openzeppelin-upgradeability/BaseUpgradeabilityProxy.sol'; + +/** + * @title BaseImmutableAdminUpgradeabilityProxy + * @author Aave, inspired by the OpenZeppelin upgradeability proxy pattern + * @dev This contract combines an upgradeability proxy with an authorization + * mechanism for administrative tasks. The admin role is stored in an immutable, which + * helps saving transactions costs + * All external functions in this contract must be guarded by the + * `ifAdmin` modifier. See ethereum/solidity#3864 for a Solidity + * feature proposal that would enable this to be done automatically. + */ +contract BaseImmutableAdminUpgradeabilityProxy is BaseUpgradeabilityProxy { + + address immutable ADMIN; + + constructor(address admin) public { + ADMIN = admin; + } + + modifier ifAdmin() { + if (msg.sender == ADMIN) { + _; + } else { + _fallback(); + } + } + + /** + * @return The address of the proxy admin. + */ + function admin() external ifAdmin returns (address) { + return ADMIN; + } + + /** + * @return The address of the implementation. + */ + function implementation() external ifAdmin returns (address) { + return _implementation(); + } + + /** + * @dev Upgrade the backing implementation of the proxy. + * Only the admin can call this function. + * @param newImplementation Address of the new implementation. + */ + function upgradeTo(address newImplementation) external ifAdmin { + _upgradeTo(newImplementation); + } + + /** + * @dev Upgrade the backing implementation of the proxy and call a function + * on the new implementation. + * This is useful to initialize the proxied contract. + * @param newImplementation Address of the new implementation. + * @param data Data to send as msg.data in the low level call. + * It should include the signature and the parameters of the function to be called, as described in + * https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding. + */ + function upgradeToAndCall(address newImplementation, bytes calldata data) + external + payable + ifAdmin + { + _upgradeTo(newImplementation); + (bool success, ) = newImplementation.delegatecall(data); + require(success); + } + + + /** + * @dev Only fall back when the sender is not the admin. + */ + function _willFallback() internal virtual override { + require(msg.sender != ADMIN, 'Cannot call fallback function from the proxy admin'); + super._willFallback(); + } +} diff --git a/contracts/libraries/aave-upgradeability/InitializableImmutableAdminUpgradeabilityProxy.sol b/contracts/libraries/aave-upgradeability/InitializableImmutableAdminUpgradeabilityProxy.sol new file mode 100644 index 00000000..9e24d896 --- /dev/null +++ b/contracts/libraries/aave-upgradeability/InitializableImmutableAdminUpgradeabilityProxy.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: agpl-3.0 +pragma solidity ^0.6.8; + +import './BaseImmutableAdminUpgradeabilityProxy.sol'; +import '../openzeppelin-upgradeability/InitializableUpgradeabilityProxy.sol'; + +/** + * @title InitializableAdminUpgradeabilityProxy + * @dev Extends from BaseAdminUpgradeabilityProxy with an initializer for + * initializing the implementation, admin, and init data. + */ +contract InitializableImmutableAdminUpgradeabilityProxy is + BaseImmutableAdminUpgradeabilityProxy, + InitializableUpgradeabilityProxy +{ + + constructor(address admin) public BaseImmutableAdminUpgradeabilityProxy(admin) { + } + + /** + * @dev Only fall back when the sender is not the admin. + */ + function _willFallback() internal override(BaseImmutableAdminUpgradeabilityProxy, Proxy) { + BaseImmutableAdminUpgradeabilityProxy._willFallback(); + } +}