Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade scripting #1188

Merged
merged 14 commits into from
Jan 10, 2025
8 changes: 4 additions & 4 deletions AllContractsHashes.json
Original file line number Diff line number Diff line change
Expand Up @@ -1712,10 +1712,10 @@
"zkBytecodePath": null
},
{
"contractName": "l1-contracts/CreateAndTransfer",
"evmBytecodeHash": "0x3ef11e5b831a5114a37d3daa2265740bd39b5302b11d972a872462c747f991ed",
"evmBytecodePath": "/l1-contracts/out/CreateAndTransfer.sol/CreateAndTransfer.json",
"evmDeployedBytecodeHash": "0xae6d5f0e37eb646c6f61340d8ba97f1c23f3b022500f99c089e5ef95a6332c87",
"contractName": "l1-contracts/Create2AndTransfer",
"evmBytecodeHash": "0x95d7ded2a7e878aa82674a330a2b3638b0efa6168a4e0af9b30afdf68384cabb",
"evmBytecodePath": "/l1-contracts/out/Create2AndTransfer.sol/Create2AndTransfer.json",
"evmDeployedBytecodeHash": "0xdfaa9e7594513b81050146de2564399318a7f5be75c6b55bda5309368de2d6c1",
"zkBytecodeHash": null,
"zkBytecodePath": null
},
Expand Down
2 changes: 2 additions & 0 deletions l1-contracts/.env
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,5 @@ ZK_CHAIN_CONFIG=/script-config/register-zk-chain.toml
ZK_CHAIN_OUTPUT=/script-out/output-deploy-zk-chain-era.toml
FORCE_DEPLOYMENTS_CONFIG=/script-config/generate-force-deployments-data.toml
GATEWAY_PREPARATION_L1_CONFIG=/script-config/gateway-preparation-l1.toml
GATEWAY_UPGRADE_ECOSYSTEM_INPUT=/script-config/gateway-upgrade-ecosystem.toml
GATEWAY_UPGRADE_ECOSYSTEM_OUTPUT=/script-out/gateway-upgrade-ecosystem.toml
26 changes: 26 additions & 0 deletions l1-contracts/deploy-scripts/AcceptAdmin.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {IGovernance} from "contracts/governance/IGovernance.sol";
import {stdToml} from "forge-std/StdToml.sol";
import {Diamond} from "contracts/state-transition/libraries/Diamond.sol";
import {ValidatorTimelock} from "contracts/state-transition/ValidatorTimelock.sol";
import {L2WrappedBaseTokenStore} from "contracts/bridge/L2WrappedBaseTokenStore.sol";

bytes32 constant SET_TOKEN_MULTIPLIER_SETTER_ROLE = keccak256("SET_TOKEN_MULTIPLIER_SETTER_ROLE");

Expand Down Expand Up @@ -226,4 +227,29 @@ contract AcceptAdmin is Script {

Utils.adminExecute(adminAddr, accessControlRestriction, validatorTimelock, data, 0);
}

/// @notice Adds L2WrappedBaseToken of a chain to the store.
/// @param storeAddress THe address of the `L2WrappedBaseTokenStore`.
/// @param ecosystemAdmin The address of the ecosystem admin contract.
/// @param chainId The chain id of the chain.
/// @param l2WBaseToken The address of the L2WrappedBaseToken.
function addL2WethToStore(
StanislavBreadless marked this conversation as resolved.
Show resolved Hide resolved
address storeAddress,
ChainAdmin ecosystemAdmin,
uint256 chainId,
address l2WBaseToken
) public {
L2WrappedBaseTokenStore l2WrappedBaseTokenStore = L2WrappedBaseTokenStore(storeAddress);

Call[] memory calls = new Call[](1);
calls[0] = Call({
target: storeAddress,
value: 0,
data: abi.encodeCall(l2WrappedBaseTokenStore.initializeChain, (chainId, l2WBaseToken))
});

vm.startBroadcast();
ecosystemAdmin.multicall(calls, true);
vm.stopBroadcast();
}
}
26 changes: 26 additions & 0 deletions l1-contracts/deploy-scripts/Create2AndTransfer.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// SPDX-License-Identifier: MIT

import {Ownable} from "@openzeppelin/contracts-v4/access/Ownable.sol";

pragma solidity 0.8.24;

/// @title Create2AndTransfer
/// @author Matter Labs
/// @custom:security-contact [email protected]
/// @dev Allows to deterministically create a contract with a fixed owner.
contract Create2AndTransfer {
/// @notice The address of the contract deployed during inside the constructor.
address public immutable deployedAddress;

constructor(bytes memory bytecode, bytes32 salt, address owner) {
address addr;
assembly {
addr := create2(0x0, add(bytecode, 0x20), mload(bytecode), salt)
}

require(addr != address(0), "Create2: Failed on deploy");
Ownable(addr).transferOwnership(owner);

deployedAddress = addr;
}
}
17 changes: 0 additions & 17 deletions l1-contracts/deploy-scripts/CreateAndTransfer.sol

This file was deleted.

8 changes: 4 additions & 4 deletions l1-contracts/deploy-scripts/RegisterZKChain.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import {Ownable2Step} from "@openzeppelin/contracts-v4/access/Ownable2Step.sol";
import {Call} from "contracts/governance/Common.sol";

import {ETH_TOKEN_ADDRESS} from "contracts/common/Config.sol";
import {CreateAndTransfer} from "./CreateAndTransfer.sol";
import {Create2AndTransfer} from "./Create2AndTransfer.sol";
import {ChainAdminOwnable} from "contracts/governance/ChainAdminOwnable.sol";

// solhint-disable-next-line gas-struct-packing
Expand Down Expand Up @@ -460,10 +460,10 @@ contract RegisterZKChainScript is Script {

function deployChainProxyAddress() internal {
bytes memory input = abi.encode(type(ProxyAdmin).creationCode, config.create2Salt, output.chainAdmin);
bytes memory encoded = abi.encodePacked(type(CreateAndTransfer).creationCode, input);
address createAndTransfer = Utils.deployViaCreate2(encoded, config.create2Salt, config.create2FactoryAddress);
bytes memory encoded = abi.encodePacked(type(Create2AndTransfer).creationCode, input);
address create2AndTransfer = Utils.deployViaCreate2(encoded, config.create2Salt, config.create2FactoryAddress);

address proxyAdmin = vm.computeCreate2Address(config.create2Salt, keccak256(encoded), createAndTransfer);
address proxyAdmin = vm.computeCreate2Address(config.create2Salt, keccak256(encoded), create2AndTransfer);

console.log("Transparent Proxy Admin deployed at:", address(proxyAdmin));
output.chainProxyAdmin = address(proxyAdmin);
Expand Down
17 changes: 11 additions & 6 deletions l1-contracts/deploy-scripts/upgrade/BytecodePublisher.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ library BytecodePublisher {
uint256 currentBatchSize = 0;
uint256 batchStartIndex = 0;

bytes[] memory toPublish = new bytes[](bytecodes.length);
uint256 toPublishPtr = 0;

for (uint256 i = 0; i < totalBytecodes; i++) {
bytes32 hash = L2ContractHelper.hashL2Bytecode(bytecodes[i]);
if (bytecodesSupplier.publishingBlock(hash) != 0) {
Expand All @@ -49,20 +52,22 @@ library BytecodePublisher {
// Check if adding this bytecode exceeds the MAX_BATCH_SIZE
if (currentBatchSize + bytecodeSize > MAX_BATCH_SIZE) {
// Publish the current batch
bytes[] memory currentBatch = slice(bytecodes, batchStartIndex, i);
bytes[] memory currentBatch = slice(toPublish, 0, toPublishPtr);
_publishBatch(bytecodesSupplier, currentBatch);

// Reset for the next batch
batchStartIndex = i;
currentBatchSize = bytecodeSize;
} else {
currentBatchSize += bytecodeSize;
toPublishPtr = 0;
currentBatchSize = 0;
}

currentBatchSize += bytecodeSize;
toPublish[toPublishPtr++] = bytecodes[i];
}

// Publish the last batch if any
if (batchStartIndex < totalBytecodes) {
bytes[] memory lastBatch = slice(bytecodes, batchStartIndex, totalBytecodes);
if (toPublishPtr != 0) {
bytes[] memory lastBatch = slice(toPublish, 0, toPublishPtr);
_publishBatch(bytecodesSupplier, lastBatch);
}
}
Expand Down
86 changes: 5 additions & 81 deletions l1-contracts/deploy-scripts/upgrade/ChainUpgrade.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,33 +13,22 @@ import {IAdmin} from "contracts/state-transition/chain-interfaces/IAdmin.sol";
import {AccessControlRestriction} from "contracts/governance/AccessControlRestriction.sol";
import {ChainAdmin} from "contracts/governance/ChainAdmin.sol";
import {Call} from "contracts/governance/Common.sol";
import {ChainTypeManager} from "contracts/state-transition/ChainTypeManager.sol";
import {Bridgehub} from "contracts/bridgehub/Bridgehub.sol";
import {Diamond} from "contracts/state-transition/libraries/Diamond.sol";

interface LegacyChainAdmin {
function owner() external view returns (address);
}

contract ChainUpgrade is Script {
using stdToml for string;

struct ChainConfig {
address deployerAddress;
address ownerAddress;
uint256 chainChainId;
address chainDiamondProxyAddress;
bool permanentRollup;
address bridgehubProxyAddress;
address oldSharedBridgeProxyAddress;
}

struct Output {
address accessControlRestriction;
address chainAdmin;
}

address currentChainAdmin;
ChainConfig config;
Output output;

function prepareChain(
string memory ecosystemInputPath,
Expand All @@ -55,14 +44,8 @@ contract ChainUpgrade is Script {

initializeConfig(configPath, ecosystemInputPath, ecosystemOutputPath);

checkCorrectOwnerAddress();

governanceMoveToNewChainAdmin();

// This script does nothing, it only checks that the provided inputs are correct.
// It is just a wrapper to easily call `upgradeChain`

saveOutput(outputPath);
}

function run() public {
Expand All @@ -79,8 +62,8 @@ contract ChainUpgrade is Script {

function upgradeChain(uint256 oldProtocolVersion, Diamond.DiamondCutData memory upgradeCutData) public {
Utils.adminExecute(
output.chainAdmin,
output.accessControlRestriction,
IZKChain(config.chainDiamondProxyAddress).getAdmin(),
address(0),
StanislavBreadless marked this conversation as resolved.
Show resolved Hide resolved
config.chainDiamondProxyAddress,
abi.encodeCall(IAdmin.upgradeChainFromVersion, (oldProtocolVersion, upgradeCutData)),
0
Expand All @@ -101,70 +84,11 @@ contract ChainUpgrade is Script {
// are parsed alfabetically and not by key.
// https://book.getfoundry.sh/cheatcodes/parse-toml

config.ownerAddress = toml.readAddress("$.owner_address");
config.chainChainId = toml.readUint("$.chain.chain_id");
config.chainDiamondProxyAddress = toml.readAddress("$.chain.diamond_proxy_address");
config.permanentRollup = toml.readBool("$.chain.permanent_rollup");

toml = vm.readFile(ecosystemInputPath);

config.bridgehubProxyAddress = toml.readAddress("$.contracts.bridgehub_proxy_address");
config.oldSharedBridgeProxyAddress = toml.readAddress("$.contracts.old_shared_bridge_proxy_address");
}

function checkCorrectOwnerAddress() internal {
currentChainAdmin = address(IZKChain(config.chainDiamondProxyAddress).getAdmin());
address currentAdminOwner = LegacyChainAdmin(currentChainAdmin).owner();

require(currentAdminOwner == config.ownerAddress, "Only the owner of the chain admin can call this function");
}

// TODO(EVM-924): this function is not used.
function deployNewChainAdmin() internal {
vm.broadcast(config.ownerAddress);
AccessControlRestriction accessControlRestriction = new AccessControlRestriction(0, config.ownerAddress);

address[] memory restrictions;
restrictions = new address[](1);
restrictions[0] = address(accessControlRestriction);

vm.broadcast(config.ownerAddress);
ChainAdmin newChainAdmin = new ChainAdmin(restrictions);
output.chainAdmin = address(newChainAdmin);
output.accessControlRestriction = address(accessControlRestriction);
}

/// @dev The caller of this function needs to be the owner of the chain admin
/// of the
function governanceMoveToNewChainAdmin() internal {
// Firstly, we need to call the legacy chain admin to transfer the ownership to the new chain admin
Call[] memory calls = new Call[](1);
calls[0] = Call({
target: config.chainDiamondProxyAddress,
value: 0,
data: abi.encodeCall(IAdmin.setPendingAdmin, (output.chainAdmin))
});

vm.startBroadcast(config.ownerAddress);
ChainAdmin(payable(currentChainAdmin)).multicall(calls, true);
vm.stopBroadcast();

// Now we need to accept the adminship
Utils.adminExecute({
_admin: output.chainAdmin,
_accessControlRestriction: output.accessControlRestriction,
_target: config.chainDiamondProxyAddress,
_data: abi.encodeCall(IAdmin.acceptAdmin, ()),
_value: 0
});
}

function saveOutput(string memory outputPath) internal {
vm.serializeAddress("root", "chain_admin_addr", output.chainAdmin);

string memory toml = vm.serializeAddress("root", "access_control_restriction", output.accessControlRestriction);
string memory root = vm.projectRoot();
vm.writeToml(toml, outputPath);
console.log("Output saved at:", outputPath);
config.chainDiamondProxyAddress = Bridgehub(config.bridgehubProxyAddress).getHyperchain(config.chainChainId);
}
}
Loading
Loading