Skip to content

Commit

Permalink
Fix token info upon migration (#760)
Browse files Browse the repository at this point in the history
  • Loading branch information
StanislavBreadless authored Sep 2, 2024
1 parent 73ddd6d commit 3a1aecc
Show file tree
Hide file tree
Showing 10 changed files with 75 additions and 53 deletions.
47 changes: 27 additions & 20 deletions l1-contracts/contracts/bridgehub/Bridgehub.sol
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import {AddressAliasHelper} from "../vendor/AddressAliasHelper.sol";
import {IMessageRoot} from "./IMessageRoot.sol";
import {ISTMDeploymentTracker} from "./ISTMDeploymentTracker.sol";
import {L2CanonicalTransaction} from "../common/Messaging.sol";
import {HyperchainLimitReached, Unauthorized, STMAlreadyRegistered, STMNotRegistered, ZeroChainId, ChainIdTooBig, SharedBridgeNotSet, BridgeHubAlreadyRegistered, AddressTooLow, MsgValueMismatch, WrongMagicValue, ZeroAddress} from "../common/L1ContractErrors.sol";
import {AssetHandlerNotRegistered, HyperchainLimitReached, Unauthorized, STMAlreadyRegistered, STMNotRegistered, ZeroChainId, ChainIdTooBig, SharedBridgeNotSet, BridgeHubAlreadyRegistered, AddressTooLow, MsgValueMismatch, WrongMagicValue, ZeroAddress} from "../common/L1ContractErrors.sol";

/// @author Matter Labs
/// @custom:security-contact security@matterlabs.dev
Expand Down Expand Up @@ -80,7 +80,8 @@ contract Bridgehub is IBridgehub, ReentrancyGuard, Ownable2StepUpgradeable, Paus
mapping(uint256 chainId => bytes32) public baseTokenAssetId;

/// @notice The deployment tracker for the state transition managers.
ISTMDeploymentTracker public stmDeployer;
/// @dev The L1 address of the stm deployer is provided.
ISTMDeploymentTracker public l1StmDeployer;

/// @dev asset info used to identify chains in the Shared Bridge
mapping(bytes32 stmAssetId => address stmAddress) public stmAssetIdToAddress;
Expand Down Expand Up @@ -140,7 +141,7 @@ contract Bridgehub is IBridgehub, ReentrancyGuard, Ownable2StepUpgradeable, Paus

// Note that this assumes that the bridgehub only accepts transactions on chains with ETH base token only.
// This is indeed true, since the only methods where this immutable is used are the ones with `onlyL1` modifier.
ETH_TOKEN_ASSET_ID = DataEncoding.encodeNTVAssetId(block.chainid, ETH_TOKEN_ADDRESS);
ETH_TOKEN_ASSET_ID = DataEncoding.encodeNTVAssetId(L1_CHAIN_ID, ETH_TOKEN_ADDRESS);
_transferOwnership(_owner);
whitelistedSettlementLayers[_l1ChainId] = true;
}
Expand Down Expand Up @@ -189,15 +190,15 @@ contract Bridgehub is IBridgehub, ReentrancyGuard, Ownable2StepUpgradeable, Paus
/// @notice To set the addresses of some of the ecosystem contracts, only Owner. Not done in initialize, as
/// the order of deployment is Bridgehub, other contracts, and then we call this.
/// @param _sharedBridge the shared bridge address
/// @param _stmDeployer the stm deployment tracker address
/// @param _l1StmDeployer the stm deployment tracker address. Note, that the address of the L1 STM deployer is provided.
/// @param _messageRoot the message root address
function setAddresses(
address _sharedBridge,
ISTMDeploymentTracker _stmDeployer,
ISTMDeploymentTracker _l1StmDeployer,
IMessageRoot _messageRoot
) external onlyOwner {
sharedBridge = IL1AssetRouter(_sharedBridge);
stmDeployer = _stmDeployer;
l1StmDeployer = _l1StmDeployer;
messageRoot = _messageRoot;
}

Expand Down Expand Up @@ -280,19 +281,19 @@ contract Bridgehub is IBridgehub, ReentrancyGuard, Ownable2StepUpgradeable, Paus
/// @param _assetAddress the asset handler address
function setAssetHandlerAddress(bytes32 _additionalData, address _assetAddress) external {
// It is a simplified version of the logic used by the AssetRouter to manage asset handlers.
// STM's assetId is `keccak256(abi.encode(L1_CHAIN_ID, stmDeployer, stmAddress))`.
// And the STMDeployer is considered the deployment tracker for the STM asset.
// STM's assetId is `keccak256(abi.encode(L1_CHAIN_ID, l1StmDeployer, stmAddress))`.
// And the l1StmDeployer is considered the deployment tracker for the STM asset.
//
// The STMDeployer will call this method to set the asset handler address for the assetId.
// The l1StmDeployer will call this method to set the asset handler address for the assetId.
// If the chain is not the same as L1, we assume that it is done via L1->L2 communication and so we unalias the sender.
//
// For simpler handling we allow anyone to call this method. It is okay, since during bridging operations
// it is double checked that `assetId` is indeed derived from the `stmDeployer`.
// it is double checked that `assetId` is indeed derived from the `l1StmDeployer`.
// TODO(EVM-703): This logic should be revised once interchain communication is implemented.

address sender = L1_CHAIN_ID == block.chainid ? msg.sender : AddressAliasHelper.undoL1ToL2Alias(msg.sender);
// This method can be accessed by STMDeployer only
require(sender == address(stmDeployer), "BH: not stm deployer");
// This method can be accessed by l1StmDeployer only
require(sender == address(l1StmDeployer), "BH: not stm deployer");
require(stateTransitionManagerIsRegistered[_assetAddress], "STM not registered");

bytes32 assetInfo = keccak256(abi.encode(L1_CHAIN_ID, sender, _additionalData));
Expand Down Expand Up @@ -341,9 +342,6 @@ contract Bridgehub is IBridgehub, ReentrancyGuard, Ownable2StepUpgradeable, Paus
revert STMNotRegistered();
}

// if (!tokenIsRegistered[_baseToken]) {
// revert TokenNotRegistered(_baseToken);
// }
require(assetIdIsRegistered[_baseTokenAssetId], "BH: asset id not registered");

if (address(sharedBridge) == address(0)) {
Expand Down Expand Up @@ -389,10 +387,14 @@ contract Bridgehub is IBridgehub, ReentrancyGuard, Ownable2StepUpgradeable, Paus
/// @notice baseToken function, which takes chainId as input, reads assetHandler from AR, and tokenAddress from AH
function baseToken(uint256 _chainId) public view returns (address) {
bytes32 baseTokenAssetId = baseTokenAssetId[_chainId];
IL1BaseTokenAssetHandler assetHandlerAddress = IL1BaseTokenAssetHandler(
sharedBridge.assetHandlerAddress(baseTokenAssetId)
);
return assetHandlerAddress.tokenAddress(baseTokenAssetId);
address assetHandlerAddress = sharedBridge.assetHandlerAddress(baseTokenAssetId);

// It is possible that the asset handler is not deployed for a chain on the current layer.
// In this case we throw an error.
if (assetHandlerAddress == address(0)) {
revert AssetHandlerNotRegistered(baseTokenAssetId);
}
return IL1BaseTokenAssetHandler(assetHandlerAddress).tokenAddress(baseTokenAssetId);
}

/// @notice Returns all the registered hyperchain addresses
Expand Down Expand Up @@ -425,7 +427,7 @@ contract Bridgehub is IBridgehub, ReentrancyGuard, Ownable2StepUpgradeable, Paus
}

function stmAssetId(address _stmAddress) public view override returns (bytes32) {
return keccak256(abi.encode(L1_CHAIN_ID, address(stmDeployer), bytes32(uint256(uint160(_stmAddress)))));
return keccak256(abi.encode(L1_CHAIN_ID, address(l1StmDeployer), bytes32(uint256(uint160(_stmAddress)))));
}

/*//////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -702,6 +704,7 @@ contract Bridgehub is IBridgehub, ReentrancyGuard, Ownable2StepUpgradeable, Paus
);
BridgehubMintSTMAssetData memory bridgeMintStruct = BridgehubMintSTMAssetData({
chainId: bridgeData.chainId,
baseTokenAssetId: baseTokenAssetId[bridgeData.chainId],
stmData: stmMintData,
chainData: chainMintData
});
Expand All @@ -723,6 +726,10 @@ contract Bridgehub is IBridgehub, ReentrancyGuard, Ownable2StepUpgradeable, Paus

settlementLayer[bridgeData.chainId] = block.chainid;
stateTransitionManager[bridgeData.chainId] = stm;
baseTokenAssetId[bridgeData.chainId] = bridgeData.baseTokenAssetId;
// To keep `assetIdIsRegistered` consistent, we'll also automatically register the base token.
// It is assumed that if the bridging happened, the token was approved on L1 already.
assetIdIsRegistered[bridgeData.baseTokenAssetId] = true;

address hyperchain = getHyperchain(bridgeData.chainId);
bool contractAlreadyDeployed = hyperchain != address(0);
Expand Down
5 changes: 3 additions & 2 deletions l1-contracts/contracts/bridgehub/IBridgehub.sol
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ struct L2TransactionRequestTwoBridgesInner {

struct BridgehubMintSTMAssetData {
uint256 chainId;
bytes32 baseTokenAssetId;
bytes stmData;
bytes chainData;
}
Expand Down Expand Up @@ -178,7 +179,7 @@ interface IBridgehub is IL1AssetHandler {

function setAddresses(
address _sharedBridge,
ISTMDeploymentTracker _stmDeployer,
ISTMDeploymentTracker _l1StmDeployer,
IMessageRoot _messageRoot
) external;

Expand Down Expand Up @@ -216,7 +217,7 @@ interface IBridgehub is IL1AssetHandler {

function stmAssetId(address _stmAddress) external view returns (bytes32);

function stmDeployer() external view returns (ISTMDeploymentTracker);
function l1StmDeployer() external view returns (ISTMDeploymentTracker);

function stmAssetIdToAddress(bytes32 _assetInfo) external view returns (address);

Expand Down
2 changes: 2 additions & 0 deletions l1-contracts/contracts/common/L1ContractErrors.sol
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,8 @@ error ZeroChainId();

error AssetIdNotSupported(bytes32 assetId);

error AssetHandlerNotRegistered(bytes32 assetId);

enum SharedBridgeKey {
PostUpgradeFirstBatch,
LegacyBridgeFirstBatch,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,7 @@ contract StateTransitionManager is IStateTransitionManager, ReentrancyGuard, Own
// genesis upgrade, deploys some contracts, sets chainId
IAdmin(hyperchainAddress).genesisUpgrade(
l1GenesisUpgrade,
address(IBridgehub(BRIDGE_HUB).stmDeployer()),
address(IBridgehub(BRIDGE_HUB).l1StmDeployer()),
_forceDeploymentData,
_factoryDeps
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,11 @@ struct ZkSyncHyperchainStorage {
address pendingAdmin;
/// @dev Fee params used to derive gasPrice for the L1->L2 transactions. For L2 transactions,
/// the bootloader gives enough freedom to the operator.
/// @dev The value is only for the L1 deployment of the ZK Chain, since payment for all the priority transactions is
/// charged at that level.
FeeParams feeParams;
/// @dev Address of the blob versioned hash getter smart contract used for EIP-4844 versioned hashes.
/// @dev Used only for testing.
address blobVersionedHashRetriever;
/// @dev The chainId of the chain
uint256 chainId;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import {IZkSyncHyperchainBase} from "./IZkSyncHyperchainBase.sol";
/// @title The interface of the Getters Contract that implements functions for getting contract state from outside the blockchain.
/// @author Matter Labs
/// @custom:security-contact security@matterlabs.dev
/// @dev Most of the methods simply return the values that correspond to the current diamond proxy and possibly
/// not to the ZK Chain as a whole. For example, if the chain is migrated to another settlement layer, the values returned
/// by this facet will correspond to the values stored on this chain and possilbly not the canonical state of the chain.
interface IGetters is IZkSyncHyperchainBase {
/*//////////////////////////////////////////////////////////////
CUSTOM GETTERS
Expand Down
2 changes: 1 addition & 1 deletion l1-contracts/contracts/upgrades/IL1GenesisUpgrade.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ interface IL1GenesisUpgrade {
address _l1GenesisUpgrade,
uint256 _chainId,
uint256 _protocolVersion,
address _stmDeployerAddress,
address _l1StmDeployerAddress,
bytes calldata _forceDeployments,
bytes[] calldata _factoryDeps
) external returns (bytes32);
Expand Down
4 changes: 2 additions & 2 deletions l1-contracts/contracts/upgrades/L1GenesisUpgrade.sol
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ contract L1GenesisUpgrade is IL1GenesisUpgrade, BaseZkSyncUpgradeGenesis {
address _l1GenesisUpgrade,
uint256 _chainId,
uint256 _protocolVersion,
address _stmDeployerAddress,
address _l1StmDeployerAddress,
bytes calldata _forceDeploymentsData,
bytes[] calldata _factoryDeps
) public override returns (bytes32) {
Expand All @@ -37,7 +37,7 @@ contract L1GenesisUpgrade is IL1GenesisUpgrade, BaseZkSyncUpgradeGenesis {
{
bytes memory l2GenesisUpgradeCalldata = abi.encodeCall(
IL2GenesisUpgrade.genesisUpgrade,
(_chainId, _stmDeployerAddress, _forceDeploymentsData)
(_chainId, _l1StmDeployerAddress, _forceDeploymentsData)
);
complexUpgraderCalldata = abi.encodeCall(
IComplexUpgrader.upgrade,
Expand Down
8 changes: 7 additions & 1 deletion l1-contracts/test/foundry/integration/GatewayTests.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -248,11 +248,13 @@ contract GatewayTests is L1ContractDeployer, HyperchainDeployer, TokenDeployer,
bridgehub.registerSettlementLayer(gatewayChainId, true);
vm.stopBroadcast();

bytes32 baseTokenAssetId = keccak256("baseTokenAssetId");
bytes memory initialDiamondCut = l1Script.getInitialDiamondCutData();
bytes memory chainData = abi.encode(AdminFacet(address(migratingChain)).prepareChainCommitment());
bytes memory stmData = abi.encode(address(1), msg.sender, stm.protocolVersion(), initialDiamondCut);
bytes memory stmData = abi.encode(baseTokenAssetId, msg.sender, stm.protocolVersion(), initialDiamondCut);
BridgehubMintSTMAssetData memory data = BridgehubMintSTMAssetData({
chainId: mintChainId,
baseTokenAssetId: baseTokenAssetId,
stmData: stmData,
chainData: chainData
});
Expand All @@ -263,6 +265,10 @@ contract GatewayTests is L1ContractDeployer, HyperchainDeployer, TokenDeployer,
bridgehub.bridgeMint(gatewayChainId, assetId, bridgehubMintData);
vm.stopBroadcast();
vm.chainId(currentChainId);

assertEq(bridgehub.baseTokenAssetId(mintChainId), baseTokenAssetId);
IZkSyncHyperchain mintedHyperchain = IZkSyncHyperchain(bridgehub.getHyperchain(mintChainId));
assertEq(mintedHyperchain.getBaseTokenAssetId(), baseTokenAssetId);
}

// add this to be excluded from coverage report
Expand Down
Loading

0 comments on commit 3a1aecc

Please sign in to comment.