Merge branch 'fix/64' into 'master'

Resolve "Optimize the proxies to remove state loads from the admin"

Closes #64

See merge request aave-tech/protocol-v2!71
This commit is contained in:
Ernesto Boado 2020-10-15 07:37:28 +00:00
commit 50760a3036
4 changed files with 122 additions and 12 deletions

View File

@ -3,8 +3,8 @@ pragma solidity ^0.6.8;
import {Ownable} from '@openzeppelin/contracts/access/Ownable.sol'; import {Ownable} from '@openzeppelin/contracts/access/Ownable.sol';
import { import {
InitializableAdminUpgradeabilityProxy InitializableImmutableAdminUpgradeabilityProxy
} from '../libraries/openzeppelin-upgradeability/InitializableAdminUpgradeabilityProxy.sol'; } from '../libraries/aave-upgradeability/InitializableImmutableAdminUpgradeabilityProxy.sol';
import {ILendingPoolAddressesProvider} from '../interfaces/ILendingPoolAddressesProvider.sol'; import {ILendingPoolAddressesProvider} from '../interfaces/ILendingPoolAddressesProvider.sol';
@ -153,14 +153,14 @@ contract LendingPoolAddressesProvider is Ownable, ILendingPoolAddressesProvider
function _updateImpl(bytes32 id, address newAddress) internal { function _updateImpl(bytes32 id, address newAddress) internal {
address payable proxyAddress = payable(_addresses[id]); address payable proxyAddress = payable(_addresses[id]);
InitializableAdminUpgradeabilityProxy proxy = InitializableAdminUpgradeabilityProxy( InitializableImmutableAdminUpgradeabilityProxy proxy = InitializableImmutableAdminUpgradeabilityProxy(
proxyAddress proxyAddress
); );
bytes memory params = abi.encodeWithSignature('initialize(address)', address(this)); bytes memory params = abi.encodeWithSignature('initialize(address)', address(this));
if (proxyAddress == address(0)) { if (proxyAddress == address(0)) {
proxy = new InitializableAdminUpgradeabilityProxy(); proxy = new InitializableImmutableAdminUpgradeabilityProxy(address(this));
proxy.initialize(newAddress, address(this), params); proxy.initialize(newAddress, params);
_addresses[id] = address(proxy); _addresses[id] = address(proxy);
emit ProxyCreated(id, address(proxy)); emit ProxyCreated(id, address(proxy));
} else { } else {

View File

@ -7,8 +7,8 @@ import {
VersionedInitializable VersionedInitializable
} from '../libraries/openzeppelin-upgradeability/VersionedInitializable.sol'; } from '../libraries/openzeppelin-upgradeability/VersionedInitializable.sol';
import { import {
InitializableAdminUpgradeabilityProxy InitializableImmutableAdminUpgradeabilityProxy
} from '../libraries/openzeppelin-upgradeability/InitializableAdminUpgradeabilityProxy.sol'; } from '../libraries/aave-upgradeability/InitializableImmutableAdminUpgradeabilityProxy.sol';
import {ReserveConfiguration} from '../libraries/configuration/ReserveConfiguration.sol'; import {ReserveConfiguration} from '../libraries/configuration/ReserveConfiguration.sol';
import {ILendingPoolAddressesProvider} from '../interfaces/ILendingPoolAddressesProvider.sol'; import {ILendingPoolAddressesProvider} from '../interfaces/ILendingPoolAddressesProvider.sol';
import {ILendingPool} from '../interfaces/ILendingPool.sol'; import {ILendingPool} from '../interfaces/ILendingPool.sol';
@ -558,7 +558,9 @@ contract LendingPoolConfigurator is VersionedInitializable {
* @param decimals the decimals of the token * @param decimals the decimals of the token
**/ **/
function _initTokenWithProxy(address implementation, uint8 decimals) internal returns (address) { function _initTokenWithProxy(address implementation, uint8 decimals) internal returns (address) {
InitializableAdminUpgradeabilityProxy proxy = new InitializableAdminUpgradeabilityProxy();
InitializableImmutableAdminUpgradeabilityProxy proxy
= new InitializableImmutableAdminUpgradeabilityProxy(address(this));
bytes memory params = abi.encodeWithSignature( bytes memory params = abi.encodeWithSignature(
'initialize(uint8,string,string)', 'initialize(uint8,string,string)',
@ -567,7 +569,7 @@ contract LendingPoolConfigurator is VersionedInitializable {
IERC20Detailed(implementation).symbol() IERC20Detailed(implementation).symbol()
); );
proxy.initialize(implementation, address(this), params); proxy.initialize(implementation, params);
return address(proxy); return address(proxy);
} }
@ -577,9 +579,9 @@ contract LendingPoolConfigurator is VersionedInitializable {
address proxyAddress, address proxyAddress,
address implementation address implementation
) internal { ) internal {
InitializableAdminUpgradeabilityProxy proxy = InitializableAdminUpgradeabilityProxy(
payable(proxyAddress) InitializableImmutableAdminUpgradeabilityProxy proxy
); = InitializableImmutableAdminUpgradeabilityProxy(payable(proxyAddress));
(uint256 decimals, , , , , , , , , , ) = pool.getReserveConfigurationData(asset); (uint256 decimals, , , , , , , , , , ) = pool.getReserveConfigurationData(asset);

View File

@ -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();
}
}

View File

@ -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();
}
}