Skip to content

Commit

Permalink
WIP POC
Browse files Browse the repository at this point in the history
  • Loading branch information
maurelian committed Jan 4, 2025
1 parent c0742df commit a947d87
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 5 deletions.
8 changes: 6 additions & 2 deletions packages/contracts-bedrock/scripts/Artifacts.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,15 @@ abstract contract Artifacts {
string memory addresses = Config.contractAddressesPath();
if (bytes(addresses).length > 0) {
console.log("Loading addresses from %s", addresses);
_loadAddresses(addresses);
loadAddresses(addresses);
}
}

/// @notice Populates the addresses to be used in a script based on a JSON file.
/// The format of the JSON file is the same that it output by this script
/// as well as the JSON files that contain addresses in the `superchain-registry`
/// repo. The JSON key is the name of the contract and the value is an address.
function _loadAddresses(string memory _path) internal {
function loadAddresses(string memory _path) public {
string memory json = Process.bash(string.concat("jq -cr < ", _path));
string[] memory keys = vm.parseJsonKeys(json, "");
for (uint256 i; i < keys.length; i++) {
Expand Down Expand Up @@ -183,6 +183,10 @@ abstract contract Artifacts {
revert InvalidDeployment("EmptyName");
}
if (bytes(_namedDeployments[_name].name).length > 0) {
// If the deployment already exists, and the address is the same, do nothing.
if (_namedDeployments[_name].addr == _deployed) {
return;
}
revert InvalidDeployment("AlreadyExists");
}

Expand Down
4 changes: 4 additions & 0 deletions packages/contracts-bedrock/scripts/deploy/Deploy.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,10 @@ contract Deploy is Deployer {
require(_isInterop == cfg.useInterop(), "Deploy: Interop setting mismatch.");

console.log("Deploying implementations");
if (bytes(_suffix).length > 0) {
console.log("saving with suffix: ", _suffix);
}

DeployImplementations di = new DeployImplementations();
(DeployImplementationsInput dii, DeployImplementationsOutput dio) = di.etchIOContracts();

Expand Down
25 changes: 24 additions & 1 deletion packages/contracts-bedrock/src/L1/OPContractsManager.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;

import { console2 as console } from "forge-std/console2.sol";
// Libraries
import { Blueprint } from "src/libraries/Blueprint.sol";
import { Constants } from "src/libraries/Constants.sol";
Expand Down Expand Up @@ -150,6 +150,12 @@ contract OPContractsManager is ISemver {
uint256 indexed outputVersion, uint256 indexed l2ChainId, address indexed deployer, bytes deployOutput
);

/// @notice Emitted when a chain is upgraded
/// @param l2ChainId Chain ID of the upgraded chain
/// @param systemConfig Address of the chain's SystemConfig contract
/// @param upgrader Address that initiated the upgrade
event Upgraded(uint256 indexed l2ChainId, ISystemConfig indexed systemConfig, address indexed upgrader);

// -------- Errors --------

/// @notice Thrown when an address is the zero address.
Expand Down Expand Up @@ -363,6 +369,23 @@ contract OPContractsManager is ISemver {
return output;
}

/// @notice Upgrades a set of chains to the latest implementation contracts
/// @param _systemConfigs Array of SystemConfig contracts, one per chain to upgrade
/// @param _proxyAdmins Array of ProxyAdmin contracts, one per chain to upgrade
/// @dev This function is intended to be called via DELEGATECALL from the Upgrade Controller Safe
function upgrade(
ISystemConfig[] calldata _systemConfigs,
IProxyAdmin[] calldata _proxyAdmins
)
external
{
for (uint256 i = 0; i < _systemConfigs.length; i++) {
ISystemConfig systemConfig = _systemConfigs[i];
IProxyAdmin proxyAdmin = _proxyAdmins[i];
proxyAdmin.upgradeAndCall(payable(address(systemConfig)), implementation.systemConfigImpl, abi.encode());
}
}

// -------- Utilities --------

/// @notice Verifies that all inputs are valid and reverts if any are invalid.
Expand Down
39 changes: 37 additions & 2 deletions packages/contracts-bedrock/test/setup/ForkLive.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol";
import { IFaultDisputeGame } from "interfaces/dispute/IFaultDisputeGame.sol";
import { IDisputeGameFactory } from "interfaces/dispute/IDisputeGameFactory.sol";
import { IAddressManager } from "interfaces/legacy/IAddressManager.sol";
import { ISystemConfig } from "interfaces/L1/ISystemConfig.sol";
import { IProxyAdmin } from "interfaces/universal/IProxyAdmin.sol";
import { OPContractsManager } from "src/L1/OPContractsManager.sol";

/// @title ForkLive
/// @notice This script is called by Setup.sol as a preparation step for the foundry test suite, and is run as an
Expand Down Expand Up @@ -97,18 +100,50 @@ contract ForkLive is Deployer {

// Now deploy the updated OPCM and implementations of the contracts
_deployNewImplementations();

// Now upgrade the contracts
_upgrade();
}

function _deployNewImplementations() internal {
// Etch a copy of the Deploy.s.sol contract so that we can use its deployImplementations() function
Deploy deployNew = Deploy(address(uint160(uint256(keccak256(abi.encode("optimism.deploy.new"))))));
vm.etch(address(deployNew), vm.getDeployedCode("Deploy.s.sol:Deploy"));
vm.label(address(deployNew), "DeployNew");
vm.allowCheatcodes(address(deployNew));
vm.setEnv("CONTRACT_ADDRESSES_PATH", string.concat(vm.projectRoot(), "/deployments/1-deploy.json"));

// Set the CONTRACT_ADDRESSES_PATH environment variable
// This is used in Deploy.setUp() to read and save the addresses it needs (SuperchainConfigProxy,
// ProtocolVersionsProxy)
string memory jsonPath = string.concat(vm.projectRoot(), "/deployments/1-deploy.json");
vm.setEnv("CONTRACT_ADDRESSES_PATH", jsonPath);
deployNew.setUp();
deployNew.cfg().setUseFaultProofs(true);
deployNew.deployImplementations({ _isInterop: false, _suffix: "_NextVersion" });

// deployNew.deployImplementations() saves the addresses to its own storage as well as to the json file at
// CONTRACT_ADDRESSES_PATH. In order to use the addresses in the json file, we now need to load them into
// local storage.
loadAddresses(jsonPath);
}

function _upgrade() internal {
OPContractsManager opcm = OPContractsManager(mustGetAddress("OPContractsManager_NextVersion"));
ISystemConfig systemConfig = ISystemConfig(mustGetAddress("SystemConfigProxy"));
IProxyAdmin proxyAdmin = IProxyAdmin(EIP1967Helper.getAdmin(address(systemConfig)));

address upgrader = proxyAdmin.owner();

ISystemConfig[] memory systemConfigs = new ISystemConfig[](1);
systemConfigs[0] = systemConfig;
IProxyAdmin[] memory proxyAdmins = new IProxyAdmin[](1);
proxyAdmins[0] = proxyAdmin;

// TODO: Add support for this prank() call to forge-std
(bool success,) = address(vm).call(abi.encodeWithSignature("prank(address,bool)", upgrader, true));
require(success, "ForkLive: Failed to prank");

(success,) = address(opcm).delegatecall(abi.encodeCall(OPContractsManager.upgrade, (systemConfigs, proxyAdmins)));
require(success, "ForkLive: Upgrade failed");
}

/// @notice Saves the proxy and implementation addresses for a contract name
Expand Down

0 comments on commit a947d87

Please sign in to comment.