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

Hyperchains deploy #28

Draft
wants to merge 8 commits into
base: hyperchains-integration-release-v23
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions l1-contracts/contracts/dev-contracts/Create2Factory.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;

contract Create2Factory {
function deploy(bytes memory _bytecode, bytes32 _salt) external returns (address contractAddress) {
require(_bytecode.length != 0, "C2F: bytecode is not set");
uint256 salt = uint256(_salt);

address predictedAddress = address(
uint160(
uint256(keccak256(abi.encodePacked(bytes1(0xff), address(this), salt, keccak256(_bytecode))))
)
);

assembly {
contractAddress := create2(callvalue(), add(_bytecode, 0x20), mload(_bytecode), salt)

if iszero(extcodesize(contractAddress)) {
revert(0, 0)
}
}

require(contractAddress == predictedAddress, "C2F: addresses mismatch");
}
}
15 changes: 12 additions & 3 deletions l1-contracts/deploy-scripts/DeployErc20.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,21 @@ contract DeployErc20Script is Script {
saveOutput();
}

function getTokensAddresses() public view returns (address[] memory) {
address[] memory addresses = new address[](config.tokens.length);
for (uint256 i = 0; i < config.tokens.length; i++) {
addresses[i] = config.tokens[i].addr;
}
return addresses;
}

function initializeConfig() internal {
config.deployerAddress = msg.sender;

string memory l1Output = "L1_OUTPUT";
string memory root = vm.projectRoot();

// Grab config from output of l1 deployment
string memory path = string.concat(root, "/script-out/output-deploy-l1.toml");
string memory path = string.concat(root, vm.envString(l1Output));
string memory toml = vm.readFile(path);

// Config file must be parsed key by key, otherwise values returned
Expand All @@ -53,7 +61,8 @@ contract DeployErc20Script is Script {
config.create2FactorySalt = vm.parseTomlBytes32(toml, "$.create2_factory_salt");

// Grab config from custom config file
path = string.concat(root, "/script-config/config-deploy-erc20.toml");
string memory tokensConfig = "TOKENS_CONFIG";
path = string.concat(root, vm.envString(tokensConfig));
toml = vm.readFile(path);

string[] memory tokens = vm.parseTomlKeys(toml, "$.tokens");
Expand Down
48 changes: 34 additions & 14 deletions l1-contracts/deploy-scripts/DeployL1.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -153,9 +153,23 @@ contract DeployL1Script is Script {
saveOutput();
}

function getBridgehubProxyAddress() public view returns (address) {
return addresses.bridgehub.bridgehubProxy;
}

function getBridgehubOwnerAddress() public view returns (address) {
Bridgehub bridgehub = Bridgehub(addresses.bridgehub.bridgehubProxy);
return bridgehub.owner();
}

function getSharedBridgeProxyAddress() public view returns (address) {
return addresses.bridges.sharedBridgeProxy;
}

function initializeConfig() internal {
string memory liConfig = "L1_CONFIG";
string memory root = vm.projectRoot();
string memory path = string.concat(root, "/script-config/config-deploy-l1.toml");
string memory path = string.concat(root, vm.envString(liConfig));
string memory toml = vm.readFile(path);

config.l1ChainId = block.chainid;
Expand Down Expand Up @@ -211,20 +225,19 @@ contract DeployL1Script is Script {
function instantiateCreate2Factory() internal {
address contractAddress;

bool isDeterministicDeployed = DETERMINISTIC_CREATE2_ADDRESS.code.length > 0;
// bool isDeterministicDeployed = DETERMINISTIC_CREATE2_ADDRESS.code.length > 0;
bool isConfigured = config.contracts.create2FactoryAddr != address(0);

if (isConfigured) {
if (config.contracts.create2FactoryAddr.code.length == 0) {
revert("Create2Factory configured address is empty");
contractAddress = Utils.deployCreate2Factory(config.contracts.create2FactorySalt);
} else {
contractAddress = config.contracts.create2FactoryAddr;
}
contractAddress = config.contracts.create2FactoryAddr;

console.log("Using configured Create2Factory address:", contractAddress);
} else if (isDeterministicDeployed) {
contractAddress = DETERMINISTIC_CREATE2_ADDRESS;
console.log("Using deterministic Create2Factory address:", contractAddress);
} else {
contractAddress = Utils.deployCreate2Factory();
contractAddress = Utils.deployCreate2Factory(config.contracts.create2FactorySalt);
console.log("Create2Factory deployed at:", contractAddress);
}

Expand Down Expand Up @@ -305,6 +318,7 @@ contract DeployL1Script is Script {
console.log("Bridgehub Implementation deployed at:", bridgehubImplementation);
addresses.bridgehub.bridgehubImplementation = bridgehubImplementation;

console.log(config.deployerAddress);
bytes memory bytecode = abi.encodePacked(
type(TransparentUpgradeableProxy).creationCode,
abi.encode(
Expand Down Expand Up @@ -459,14 +473,14 @@ contract DeployL1Script is Script {

function registerStateTransitionManager() internal {
Bridgehub bridgehub = Bridgehub(addresses.bridgehub.bridgehubProxy);
vm.broadcast();
vm.broadcast(config.deployerAddress);
bridgehub.addStateTransitionManager(addresses.stateTransition.stateTransitionProxy);
console.log("StateTransitionManager registered");
}

function setStateTransitionManagerInValidatorTimelock() internal {
ValidatorTimelock validatorTimelock = ValidatorTimelock(addresses.validatorTimelock);
vm.broadcast();
vm.broadcast(config.deployerAddress);
validatorTimelock.setStateTransitionManager(
IStateTransitionManager(addresses.stateTransition.stateTransitionProxy)
);
Expand Down Expand Up @@ -530,7 +544,7 @@ contract DeployL1Script is Script {

function registerSharedBridge() internal {
Bridgehub bridgehub = Bridgehub(addresses.bridgehub.bridgehubProxy);
vm.startBroadcast();
vm.startBroadcast(config.deployerAddress);
bridgehub.addToken(ADDRESS_ONE);
bridgehub.setSharedBridge(addresses.bridges.sharedBridgeProxy);
vm.stopBroadcast();
Expand Down Expand Up @@ -560,13 +574,13 @@ contract DeployL1Script is Script {

function updateSharedBridge() internal {
L1SharedBridge sharedBridge = L1SharedBridge(addresses.bridges.sharedBridgeProxy);
vm.broadcast();
vm.broadcast(config.deployerAddress);
sharedBridge.setL1Erc20Bridge(addresses.bridges.erc20BridgeProxy);
console.log("SharedBridge updated with ERC20Bridge address");
}

function updateOwners() internal {
vm.startBroadcast();
vm.startBroadcast(config.deployerAddress);

ValidatorTimelock validatorTimelock = ValidatorTimelock(addresses.validatorTimelock);
validatorTimelock.transferOwnership(config.ownerAddress);
Expand All @@ -579,6 +593,11 @@ contract DeployL1Script is Script {

vm.stopBroadcast();

vm.startBroadcast(addresses.governance);
bridgehub.acceptOwnership();
sharedBridge.acceptOwnership();
vm.stopBroadcast();

console.log("Owners updated");
}

Expand Down Expand Up @@ -701,7 +720,8 @@ contract DeployL1Script is Script {
vm.serializeString("root", "contracts_config", contractsConfig);
string memory toml = vm.serializeAddress("root", "owner_addr", config.ownerAddress);

string memory path = string.concat(vm.projectRoot(), "/script-out/output-deploy-l1.toml");
string memory liConfigOutput = "L1_OUTPUT";
string memory path = string.concat(vm.projectRoot(), vm.envString(liConfigOutput));
vm.writeToml(toml, path);
}

Expand Down
30 changes: 22 additions & 8 deletions l1-contracts/deploy-scripts/RegisterHyperchain.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
address bridgehub;
address stateTransitionProxy;
address validatorTimelock;
address bridgehubGovernance;
bytes diamondCutData;
address governanceSecurityCouncilAddress;
uint256 governanceMinDelay;
Expand Down Expand Up @@ -62,25 +63,31 @@

function initializeConfig() internal {
// Grab config from output of l1 deployment
string memory l1OutputConfig = "L1_OUTPUT";
string memory root = vm.projectRoot();
string memory path = string.concat(root, "/script-config/register-hyperchain.toml");
string memory path = string.concat(root, vm.envString(l1OutputConfig));
string memory toml = vm.readFile(path);

config.deployerAddress = msg.sender;

// Config file must be parsed key by key, otherwise values returned
// are parsed alfabetically and not by key.
// https://book.getfoundry.sh/cheatcodes/parse-toml
config.ownerAddress = toml.readAddress("$.owner_address");
config.ownerAddress = toml.readAddress("$.owner_addr");

config.bridgehub = toml.readAddress("$.deployed_addresses.bridgehub.bridgehub_proxy_addr");
config.stateTransitionProxy = toml.readAddress(
"$.deployed_addresses.state_transition.state_transition_proxy_addr"
);
config.validatorTimelock = toml.readAddress("$.deployed_addresses.validator_timelock_addr");

config.bridgehubGovernance = toml.readAddress("$.deployed_addresses.governance_addr");
config.diamondCutData = toml.readBytes("$.contracts_config.diamond_cut_data");

// Grab config from hyperchain deploy config
string memory hyperchainConfig = "HYPERCHAIN_CONFIG";
path = string.concat(root, vm.envString(hyperchainConfig));
toml = vm.readFile(path);

config.chainChainId = toml.readUint("$.chain.chain_chain_id");
config.bridgehubCreateNewChainSalt = toml.readUint("$.chain.bridgehub_create_new_chain_salt");
config.baseToken = toml.readAddress("$.chain.base_token_addr");
Expand Down Expand Up @@ -116,14 +123,15 @@

function registerTokenOnBridgehub() internal {
IBridgehub bridgehub = IBridgehub(config.bridgehub);
Ownable ownable = Ownable(config.bridgehub);

Check failure on line 126 in l1-contracts/deploy-scripts/RegisterHyperchain.s.sol

View workflow job for this annotation

GitHub Actions / lint

Variable "ownable" is unused

Check failure on line 126 in l1-contracts/deploy-scripts/RegisterHyperchain.s.sol

View workflow job for this annotation

GitHub Actions / lint

Variable "ownable" is unused

Check failure on line 126 in l1-contracts/deploy-scripts/RegisterHyperchain.s.sol

View workflow job for this annotation

GitHub Actions / lint

Variable "ownable" is unused

if (bridgehub.tokenIsRegistered(config.baseToken)) {
console.log("Token already registered on Bridgehub");
} else {
bytes memory data = abi.encodeCall(bridgehub.addToken, (config.baseToken));
Utils.executeUpgrade({
_governor: ownable.owner(),
_governance: config.bridgehubGovernance,
_governor: config.ownerAddress,
_salt: bytes32(config.bridgehubCreateNewChainSalt),
_target: config.bridgehub,
_data: data,
Expand All @@ -147,7 +155,7 @@

function registerHyperchain() internal {
IBridgehub bridgehub = IBridgehub(config.bridgehub);
Ownable ownable = Ownable(config.bridgehub);

Check failure on line 158 in l1-contracts/deploy-scripts/RegisterHyperchain.s.sol

View workflow job for this annotation

GitHub Actions / lint

Variable "ownable" is unused

Check failure on line 158 in l1-contracts/deploy-scripts/RegisterHyperchain.s.sol

View workflow job for this annotation

GitHub Actions / lint

Variable "ownable" is unused

Check failure on line 158 in l1-contracts/deploy-scripts/RegisterHyperchain.s.sol

View workflow job for this annotation

GitHub Actions / lint

Variable "ownable" is unused

vm.recordLogs();
bytes memory data = abi.encodeCall(
Expand All @@ -162,8 +170,11 @@
)
);



Utils.executeUpgrade({
_governor: ownable.owner(),
_governance: config.bridgehubGovernance,
_governor: config.ownerAddress,
_salt: bytes32(config.bridgehubCreateNewChainSalt),
_target: config.bridgehub,
_data: data,
Expand Down Expand Up @@ -191,7 +202,7 @@
function addValidators() internal {
ValidatorTimelock validatorTimelock = ValidatorTimelock(config.validatorTimelock);

vm.startBroadcast();
vm.startBroadcast(msg.sender);
validatorTimelock.addValidator(config.chainChainId, config.validatorSenderOperatorCommitEth);
validatorTimelock.addValidator(config.chainChainId, config.validatorSenderOperatorBlobsEth);
vm.stopBroadcast();
Expand All @@ -202,7 +213,7 @@
function configureZkSyncStateTransition() internal {
IZkSyncHyperchain hyperchain = IZkSyncHyperchain(config.newDiamondProxy);

vm.startBroadcast();
vm.startBroadcast(msg.sender);
hyperchain.setTokenMultiplier(
config.baseTokenGasPriceMultiplierNominator,
config.baseTokenGasPriceMultiplierDenominator
Expand All @@ -219,9 +230,12 @@
function setPendingAdmin() internal {
IZkSyncHyperchain hyperchain = IZkSyncHyperchain(config.newDiamondProxy);

vm.broadcast();
vm.broadcast(msg.sender);
hyperchain.setPendingAdmin(config.governance);
console.log("Owner for ", config.newDiamondProxy, "set to", config.governance);

vm.broadcast(config.governance);
hyperchain.acceptAdmin();
}

function saveOutput() internal {
Expand Down
57 changes: 20 additions & 37 deletions l1-contracts/deploy-scripts/Utils.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {REQUIRED_L2_GAS_PRICE_PER_PUBDATA} from "contracts/common/Config.sol";
import {L2_DEPLOYER_SYSTEM_CONTRACT_ADDR} from "contracts/common/L2ContractAddresses.sol";
import {L2ContractHelper} from "contracts/common/libraries/L2ContractHelper.sol";
import {Create2Factory} from "contracts/dev-contracts/Create2Factory.sol";

library Utils {
// Cheatcodes address, 0x7109709ECfa91a80626fF3989D68f67F5b1DD12D.
Expand Down Expand Up @@ -53,21 +54,16 @@ library Utils {
}

// Remove `getName()` selector if existing
bool hasGetName = false;
for (uint256 i = 0; i < selectors.length; i++) {
if (selectors[i] == bytes4(keccak256("getName()"))) {
selectors[i] = selectors[selectors.length - 1];
hasGetName = true;
// Pop the last element from the array
assembly {
mstore(selectors, sub(mload(selectors), 1))
}
break;
}
}
if (hasGetName) {
bytes4[] memory newSelectors = new bytes4[](selectors.length - 1);
for (uint256 i = 0; i < selectors.length - 1; i++) {
newSelectors[i] = selectors[i];
}
return newSelectors;
}

return selectors;
}
Expand Down Expand Up @@ -127,40 +123,25 @@ library Utils {
/**
* @dev Deploy a Create2Factory contract.
*/
function deployCreate2Factory() internal returns (address) {
address child;
bytes memory bytecode = CREATE2_FACTORY_BYTECODE;
vm.startBroadcast();
assembly {
child := create(0, add(bytecode, 0x20), mload(bytecode))
}
vm.stopBroadcast();
require(child != address(0), "Failed to deploy Create2Factory");
require(child.code.length > 0, "Failed to deploy Create2Factory");
return child;
function deployCreate2Factory(bytes32 _factorySalt) internal returns (address) {
vm.broadcast();
Create2Factory factory = new Create2Factory{salt: _factorySalt}();

address factoryAddress = address(factory);
require(factoryAddress != address(0), "Failed to deploy Create2Factory");
require(factoryAddress.code.length > 0, "Failed to deploy Create2Factory");

return factoryAddress;
}

/**
* @dev Deploys contract using CREATE2.
*/
function deployViaCreate2(bytes memory _bytecode, bytes32 _salt, address _factory) internal returns (address) {
if (_bytecode.length == 0) {
revert("Bytecode is not set");
}
address contractAddress = vm.computeCreate2Address(_salt, keccak256(_bytecode), _factory);
if (contractAddress.code.length != 0) {
return contractAddress;
}
Create2Factory factory = Create2Factory(_factory);

vm.broadcast();
(bool success, bytes memory data) = _factory.call(abi.encodePacked(_salt, _bytecode));
contractAddress = bytesToAddress(data);

if (!success || contractAddress == address(0) || contractAddress.code.length == 0) {
revert("Failed to deploy contract via create2");
}

return contractAddress;
return factory.deploy(_bytecode, _salt);
}

/**
Expand Down Expand Up @@ -289,16 +270,18 @@ library Utils {
}

function executeUpgrade(
address _governance,
address _governor,
bytes32 _salt,
address _target,
bytes memory _data,
uint256 _value,
uint256 _delay
) internal {
IGovernance governance = IGovernance(_governor);
IGovernance governance = IGovernance(_governance);

IGovernance.Call[] memory calls = new IGovernance.Call[](1);

calls[0] = IGovernance.Call({target: _target, value: _value, data: _data});

IGovernance.Operation memory operation = IGovernance.Operation({
Expand All @@ -307,7 +290,7 @@ library Utils {
salt: _salt
});

vm.startBroadcast();
vm.startBroadcast(_governor);
governance.scheduleTransparent(operation, _delay);
if (_delay == 0) {
governance.execute{value: _value}(operation);
Expand Down
Loading
Loading