Skip to content

Commit

Permalink
Merge pull request #758 from matter-labs/sb-sync-sync-layer-stable
Browse files Browse the repository at this point in the history
Sync with sync layer stable
  • Loading branch information
StanislavBreadless authored Aug 30, 2024
2 parents 989f2c1 + 464382e commit d669a5f
Show file tree
Hide file tree
Showing 11 changed files with 216 additions and 88 deletions.
78 changes: 47 additions & 31 deletions l1-contracts/contracts/bridgehub/Bridgehub.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {EnumerableMap} from "@openzeppelin/contracts-v4/utils/structs/Enumerable
import {Ownable2StepUpgradeable} from "@openzeppelin/contracts-upgradeable-v4/access/Ownable2StepUpgradeable.sol";
import {PausableUpgradeable} from "@openzeppelin/contracts-upgradeable-v4/security/PausableUpgradeable.sol";

import {IBridgehub, L2TransactionRequestDirect, L2TransactionRequestTwoBridgesOuter, L2TransactionRequestTwoBridgesInner} from "./IBridgehub.sol";
import {IBridgehub, L2TransactionRequestDirect, L2TransactionRequestTwoBridgesOuter, L2TransactionRequestTwoBridgesInner, BridgehubMintSTMAssetData, BridgehubBurnSTMAssetData} from "./IBridgehub.sol";
import {IL1AssetRouter} from "../bridge/interfaces/IL1AssetRouter.sol";
import {IL1BaseTokenAssetHandler} from "../bridge/interfaces/IL1BaseTokenAssetHandler.sol";
import {IStateTransitionManager} from "../state-transition/IStateTransitionManager.sol";
Expand Down Expand Up @@ -684,72 +684,88 @@ contract Bridgehub is IBridgehub, ReentrancyGuard, Ownable2StepUpgradeable, Paus
) external payable override onlyAssetRouter whenMigrationsNotPaused returns (bytes memory bridgehubMintData) {
require(whitelistedSettlementLayers[_settlementChainId], "BH: SL not whitelisted");

(uint256 _chainId, bytes memory _stmData, bytes memory _chainData) = abi.decode(_data, (uint256, bytes, bytes));
require(_assetId == stmAssetIdFromChainId(_chainId), "BH: assetInfo 1");
require(settlementLayer[_chainId] == block.chainid, "BH: not current SL");
settlementLayer[_chainId] = _settlementChainId;
BridgehubBurnSTMAssetData memory bridgeData = abi.decode(_data, (BridgehubBurnSTMAssetData));
require(_assetId == stmAssetIdFromChainId(bridgeData.chainId), "BH: assetInfo 1");
require(settlementLayer[bridgeData.chainId] == block.chainid, "BH: not current SL");
settlementLayer[bridgeData.chainId] = _settlementChainId;

address hyperchain = hyperchainMap.get(_chainId);
address hyperchain = hyperchainMap.get(bridgeData.chainId);
require(hyperchain != address(0), "BH: hyperchain not registered");
require(_prevMsgSender == IZkSyncHyperchain(hyperchain).getAdmin(), "BH: incorrect sender");

bytes memory stmMintData = IStateTransitionManager(stateTransitionManager[_chainId]).forwardedBridgeBurn(
_chainId,
_stmData
);
bytes memory stmMintData = IStateTransitionManager(stateTransitionManager[bridgeData.chainId])
.forwardedBridgeBurn(bridgeData.chainId, bridgeData.stmData);
bytes memory chainMintData = IZkSyncHyperchain(hyperchain).forwardedBridgeBurn(
hyperchainMap.get(_settlementChainId),
_prevMsgSender,
_chainData
bridgeData.chainData
);
bridgehubMintData = abi.encode(_chainId, stmMintData, chainMintData);
BridgehubMintSTMAssetData memory bridgeMintStruct = BridgehubMintSTMAssetData({
chainId: bridgeData.chainId,
stmData: stmMintData,
chainData: chainMintData
});
bridgehubMintData = abi.encode(bridgeMintStruct);

emit MigrationStarted(_chainId, _assetId, _settlementChainId);
emit MigrationStarted(bridgeData.chainId, _assetId, _settlementChainId);
}

/// @dev IL1AssetHandler interface, used to receive a chain on the settlement layer.
/// @param _assetId the assetId of the chain's STM
/// @param _bridgehubMintData the data for the mint
function bridgeMint(
uint256, // originChainId
bytes32 _assetId,
bytes calldata _bridgehubMintData
) external payable override onlyAssetRouter whenMigrationsNotPaused {
(uint256 _chainId, bytes memory _stmData, bytes memory _chainMintData) = abi.decode(
_bridgehubMintData,
(uint256, bytes, bytes)
);
BridgehubMintSTMAssetData memory bridgeData = abi.decode(_bridgehubMintData, (BridgehubMintSTMAssetData));

address stm = stmAssetIdToAddress[_assetId];
require(stm != address(0), "BH: assetInfo 2");
require(settlementLayer[_chainId] != block.chainid, "BH: already current SL");
require(settlementLayer[bridgeData.chainId] != block.chainid, "BH: already current SL");

settlementLayer[_chainId] = block.chainid;
stateTransitionManager[_chainId] = stm;
settlementLayer[bridgeData.chainId] = block.chainid;
stateTransitionManager[bridgeData.chainId] = stm;

address hyperchain = getHyperchain(_chainId);
address hyperchain = getHyperchain(bridgeData.chainId);
bool contractAlreadyDeployed = hyperchain != address(0);
if (!contractAlreadyDeployed) {
hyperchain = IStateTransitionManager(stm).forwardedBridgeMint(_chainId, _stmData);
hyperchain = IStateTransitionManager(stm).forwardedBridgeMint(bridgeData.chainId, bridgeData.stmData);
require(hyperchain != address(0), "BH: chain not registered");
_registerNewHyperchain(_chainId, hyperchain);
messageRoot.addNewChain(_chainId);
_registerNewHyperchain(bridgeData.chainId, hyperchain);
messageRoot.addNewChain(bridgeData.chainId);
}

IZkSyncHyperchain(hyperchain).forwardedBridgeMint(_chainMintData, contractAlreadyDeployed);
IZkSyncHyperchain(hyperchain).forwardedBridgeMint(bridgeData.chainData, contractAlreadyDeployed);

emit MigrationFinalized(_chainId, _assetId, hyperchain);
emit MigrationFinalized(bridgeData.chainId, _assetId, hyperchain);
}

/// @dev IL1AssetHandler interface, used to undo a failed migration of a chain.
/// @param _chainId the chainId of the chain
/// @param _assetId the assetId of the chain's STM
/// @param _data the data for the recovery
/// @param _data the data for the recovery.
function bridgeRecoverFailedTransfer(
uint256 _chainId,
bytes32 _assetId,
address _depositSender,
bytes calldata _data
) external payable override onlyAssetRouter whenMigrationsNotPaused {}
) external payable override onlyAssetRouter onlyL1 {
BridgehubBurnSTMAssetData memory stmAssetData = abi.decode(_data, (BridgehubBurnSTMAssetData));

delete settlementLayer[_chainId];

IStateTransitionManager(stateTransitionManager[_chainId]).forwardedBridgeRecoverFailedTransfer({
_chainId: _chainId,
_assetInfo: _assetId,
_depositSender: _depositSender,
_stmData: stmAssetData.stmData
});

IZkSyncHyperchain(getHyperchain(_chainId)).forwardedBridgeRecoverFailedTransfer({
_chainId: _chainId,
_assetInfo: _assetId,
_prevMsgSender: _depositSender,
_chainData: stmAssetData.chainData
});
}

/*//////////////////////////////////////////////////////////////
PAUSE
Expand Down
12 changes: 12 additions & 0 deletions l1-contracts/contracts/bridgehub/IBridgehub.sol
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,18 @@ struct L2TransactionRequestTwoBridgesInner {
bytes32 txDataHash;
}

struct BridgehubMintSTMAssetData {
uint256 chainId;
bytes stmData;
bytes chainData;
}

struct BridgehubBurnSTMAssetData {
uint256 chainId;
bytes stmData;
bytes chainData;
}

/// @author Matter Labs
/// @custom:security-contact [email protected]
interface IBridgehub is IL1AssetHandler {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,10 +165,10 @@ interface IStateTransitionManager {

function forwardedBridgeMint(uint256 _chainId, bytes calldata _data) external returns (address);

function bridgeClaimFailedBurn(
function forwardedBridgeRecoverFailedTransfer(
uint256 _chainId,
bytes32 _assetInfo,
address _prevMsgSender,
bytes calldata _data
address _depositSender,
bytes calldata _stmData
) external;
}
21 changes: 11 additions & 10 deletions l1-contracts/contracts/state-transition/StateTransitionManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -501,16 +501,17 @@ contract StateTransitionManager is IStateTransitionManager, ReentrancyGuard, Own
}

/// @notice Called by the bridgehub during the failed migration of a chain.
/// @param _chainId the chainId of the chain
/// @param _assetInfo the assetInfo of the chain
/// @param _prevMsgSender the previous message sender
/// @param _data the data of the migration
function bridgeClaimFailedBurn(
uint256 _chainId,
bytes32 _assetInfo,
address _prevMsgSender,
bytes calldata _data
/// param _chainId the chainId of the chain
/// param _assetInfo the assetInfo of the chain
/// param _depositSender the address of that sent the deposit
/// param _stmData the data of the migration
function forwardedBridgeRecoverFailedTransfer(
uint256 /* _chainId */,
bytes32 /* _assetInfo */,
address /* _depositSender */,
bytes calldata /* _stmData */
) external {
// todo
// Function is empty due to the fact that when calling `forwardedBridgeBurn` there are no
// state updates that occur.
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -249,14 +249,14 @@ contract AdminFacet is ZkSyncHyperchainBase, IAdmin {
function forwardedBridgeBurn(
address _settlementLayer,
address _prevMsgSender,
bytes calldata
bytes calldata _data
) external payable override onlyBridgehub returns (bytes memory chainBridgeMintData) {
require(s.settlementLayer == address(0), "Af: already migrated");
require(_prevMsgSender == s.admin, "Af: not chainAdmin");
IStateTransitionManager stm = IStateTransitionManager(s.stateTransitionManager);
// As of now all we need in this function is the chainId so we encode it and pass it down in the _chainData field
uint256 protocolVersion = abi.decode(_data, (uint256));

uint256 currentProtocolVersion = s.protocolVersion;
uint256 protocolVersion = stm.protocolVersion();

require(currentProtocolVersion == protocolVersion, "STM: protocolVersion not up to date");

Expand Down Expand Up @@ -335,12 +335,26 @@ contract AdminFacet is ZkSyncHyperchainBase, IAdmin {
}

/// @inheritdoc IAdmin
function forwardedBridgeClaimFailedBurn(
uint256 _chainId,
bytes32 _assetInfo,
address _prevMsgSender,
bytes calldata _data
) external payable override onlyBridgehub {}
/// @dev Note that this function does not check that the caller is the chain admin.
function forwardedBridgeRecoverFailedTransfer(
uint256 /* _chainId */,
bytes32 /* _assetInfo */,
address _depositSender,
bytes calldata _chainData
) external payable override onlyBridgehub {
// As of now all we need in this function is the chainId so we encode it and pass it down in the _chainData field
uint256 protocolVersion = abi.decode(_chainData, (uint256));

require(s.settlementLayer != address(0), "Af: not migrated");
// Sanity check that the _depositSender is the chain admin.
require(_depositSender == s.admin, "Af: not chainAdmin");

uint256 currentProtocolVersion = s.protocolVersion;

require(currentProtocolVersion == protocolVersion, "STM: protocolVersion not up to date");

s.settlementLayer = address(0);
}

/// @notice Returns the commitment for a chain.
/// @dev Note, that this is a getter method helpful for debugging and should not be relied upon by clients.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,11 +140,11 @@ interface IAdmin is IZkSyncHyperchainBase {
) external payable returns (bytes memory _bridgeMintData);

/// @dev Similar to IL1AssetHandler interface, used to claim failed chain transfers.
function forwardedBridgeClaimFailedBurn(
function forwardedBridgeRecoverFailedTransfer(
uint256 _chainId,
bytes32 _assetInfo,
address _prevMsgSender,
bytes calldata _data
bytes calldata _chainData
) external payable;

/// @dev Similar to IL1AssetHandler interface, used to receive chains.
Expand Down
11 changes: 8 additions & 3 deletions l1-contracts/deploy-scripts/Gateway.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {Script, console2 as console} from "forge-std/Script.sol";
import {stdToml} from "forge-std/StdToml.sol";

import {Ownable} from "@openzeppelin/contracts-v4/access/Ownable.sol";
import {IBridgehub} from "contracts/bridgehub/IBridgehub.sol";
import {IBridgehub, BridgehubBurnSTMAssetData} from "contracts/bridgehub/IBridgehub.sol";
import {IZkSyncHyperchain} from "contracts/state-transition/chain-interfaces/IZkSyncHyperchain.sol";
// import {ValidatorTimelock} from "contracts/state-transition/ValidatorTimelock.sol";
// import {Governance} from "contracts/governance/Governance.sol";
Expand Down Expand Up @@ -154,8 +154,13 @@ contract GatewayScript is Script {
bytes32 stmAssetId = bridgehub.stmAssetIdFromChainId(config.chainChainId);
bytes memory diamondCutData = config.diamondCutData; // todo replace with config.zkDiamondCutData;
bytes memory stmData = abi.encode(newAdmin, diamondCutData);
bytes memory chainData = abi.encode(address(1));
bytes memory bridgehubData = abi.encode(config.chainChainId, stmData, chainData);
bytes memory chainData = abi.encode(chain.getProtocolVersion());
BridgehubBurnSTMAssetData memory stmAssetData = BridgehubBurnSTMAssetData({
chainId: config.chainChainId,
stmData: stmData,
chainData: chainData
});
bytes memory bridgehubData = abi.encode(stmAssetData);
bytes memory routerData = bytes.concat(bytes1(0x01), abi.encode(stmAssetId, bridgehubData));

vm.startBroadcast(chain.getAdmin());
Expand Down
8 changes: 5 additions & 3 deletions l1-contracts/src.ts/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import {
compileInitialCutHash,
readBytecode,
applyL1ToL2Alias,
BRIDGEHUB_STM_ASSET_DATA_ABI_STRING,
// priorityTxMaxGasLimit,
encodeNTVAssetId,
ETH_ADDRESS_IN_CONTRACTS,
Expand Down Expand Up @@ -1143,6 +1144,8 @@ export class Deployer {

// Main function to move the current chain (that is hooked to l1), on top of the syncLayer chain.
public async moveChainToGateway(gatewayChainId: string, gasPrice: BigNumberish) {
const protocolVersion = packSemver(...unpackStringSemVer(process.env.CONTRACTS_GENESIS_PROTOCOL_SEMANTIC_VERSION));
const chainData = ethers.utils.defaultAbiCoder.encode(["uint256"], [protocolVersion]);
const bridgehub = this.bridgehubContract(this.deployWallet);
// Just some large gas limit that should always be enough
const l2GasLimit = ethers.BigNumber.from(72_000_000);
Expand All @@ -1156,10 +1159,9 @@ export class Deployer {
const initialDiamondCut = new ethers.utils.AbiCoder().encode([DIAMOND_CUT_DATA_ABI_STRING], [diamondCutData]);

const stmData = new ethers.utils.AbiCoder().encode(["uint256", "bytes"], [newAdmin, initialDiamondCut]);
const chainData = new ethers.utils.AbiCoder().encode(["uint256"], [ADDRESS_ONE]); // empty for now
const bridgehubData = new ethers.utils.AbiCoder().encode(
["uint256", "bytes", "bytes"],
[this.chainId, stmData, chainData]
[BRIDGEHUB_STM_ASSET_DATA_ABI_STRING],
[[this.chainId, stmData, chainData]]
);

// console.log("bridgehubData", bridgehubData)
Expand Down
3 changes: 1 addition & 2 deletions l1-contracts/src.ts/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@ export const DIAMOND_CUT_DATA_ABI_STRING =
"tuple(tuple(address facet, uint8 action, bool isFreezable, bytes4[] selectors)[] facetCuts, address initAddress, bytes initCalldata)";
export const FORCE_DEPLOYMENT_ABI_STRING =
"tuple(bytes32 bytecodeHash, address newAddress, bool callConstructor, uint256 value, bytes input)[]";
export const HYPERCHAIN_COMMITMENT_ABI_STRING =
"tuple(uint256 totalBatchesExecuted, uint256 totalBatchesVerified, uint256 totalBatchesCommitted, bytes32 l2SystemContractsUpgradeTxHash, uint256 l2SystemContractsUpgradeBatchNumber, bytes32[] batchHashes, tuple(uint256 nextLeafIndex, uint256 startIndex, uint256 unprocessedIndex, bytes32[] sides) priorityTree)";
export const BRIDGEHUB_STM_ASSET_DATA_ABI_STRING = "tuple(uint256 chainId, bytes stmData, bytes chainData)";

export function applyL1ToL2Alias(address: string): string {
return ethers.utils.hexlify(ethers.BigNumber.from(address).add(L1_TO_L2_ALIAS_OFFSET).mod(ADDRESS_MODULO));
Expand Down
Loading

0 comments on commit d669a5f

Please sign in to comment.