|
|
|
@ -61,16 +61,17 @@ abstract contract ERC1967Upgrade is ERC1967Storage { |
|
|
|
|
*/ |
|
|
|
|
function _upgradeToAndCallSecure(address newImplementation, bytes memory data, bool forceCall) internal { |
|
|
|
|
address oldImplementation = _getImplementation(); |
|
|
|
|
// do inital upgrade |
|
|
|
|
|
|
|
|
|
// Initial upgrade and setup call |
|
|
|
|
_setImplementation(newImplementation); |
|
|
|
|
// do setup call |
|
|
|
|
if (data.length > 0 || forceCall) { |
|
|
|
|
Address.functionDelegateCall(newImplementation, data); |
|
|
|
|
} |
|
|
|
|
// check if nested in an upgrade check |
|
|
|
|
|
|
|
|
|
// Perform rollback test if not already in progress |
|
|
|
|
StorageSlot.BooleanSlot storage rollbackTesting = StorageSlot.getBooleanSlot(_ROLLBACK_SLOT); |
|
|
|
|
if (!rollbackTesting.value) { |
|
|
|
|
// trigger upgrade check with flag set to true |
|
|
|
|
// Trigger rollback using upgradeTo from the new implementation |
|
|
|
|
rollbackTesting.value = true; |
|
|
|
|
Address.functionDelegateCall( |
|
|
|
|
newImplementation, |
|
|
|
@ -80,11 +81,10 @@ abstract contract ERC1967Upgrade is ERC1967Storage { |
|
|
|
|
) |
|
|
|
|
); |
|
|
|
|
rollbackTesting.value = false; |
|
|
|
|
// check upgrade was effective |
|
|
|
|
// Check rollback was effective |
|
|
|
|
require(oldImplementation == _getImplementation(), "ERC1967Upgrade: upgrade breaks further upgrades"); |
|
|
|
|
// reset upgrade |
|
|
|
|
// Finally reset to the new implementation and log the upgrade |
|
|
|
|
_setImplementation(newImplementation); |
|
|
|
|
// emit event |
|
|
|
|
emit Upgraded(newImplementation); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|