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

Remove Base Token Address from Chain Registration #700

Merged
merged 10 commits into from
Aug 20, 2024
34 changes: 19 additions & 15 deletions l1-contracts/contracts/bridgehub/Bridgehub.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {PausableUpgradeable} from "@openzeppelin/contracts-upgradeable/security/

import {IBridgehub, L2TransactionRequestDirect, L2TransactionRequestTwoBridgesOuter, L2TransactionRequestTwoBridgesInner} from "./IBridgehub.sol";
import {IL1AssetRouter} from "../bridge/interfaces/IL1AssetRouter.sol";
import {IL1NativeTokenVault} from "../bridge/interfaces/IL1NativeTokenVault.sol";
import {IStateTransitionManager} from "../state-transition/IStateTransitionManager.sol";
import {ReentrancyGuard} from "../common/ReentrancyGuard.sol";
import {DataEncoding} from "../common/libraries/DataEncoding.sol";
Expand Down Expand Up @@ -41,14 +42,15 @@ contract Bridgehub is IBridgehub, ReentrancyGuard, Ownable2StepUpgradeable, Paus

/// @notice StateTransitionManagers that are registered, and ZKchains that use these STMs can use this bridgehub as settlement layer.
mapping(address _stateTransitionManager => bool) public stateTransitionManagerIsRegistered;

/// @notice we store registered tokens (for arbitrary base token)
mapping(address _baseToken => bool) public tokenIsRegistered;
mapping(address _baseToken => bool) public __DEPRECATED_tokenIsRegistered;
Raid5594 marked this conversation as resolved.
Show resolved Hide resolved

/// @notice chainID => StateTransitionManager contract address, STM that is managing rules for a given ZKchain.
mapping(uint256 _chainId => address) public stateTransitionManager;

/// @notice chainID => baseToken contract address, token that is used as 'base token' by a given child chain.
mapping(uint256 _chainId => address) public baseToken;
mapping(uint256 _chainId => address) public __DEPRECATED_baseToken;

/// @dev used to manage non critical updates
address public admin;
Expand Down Expand Up @@ -187,13 +189,12 @@ contract Bridgehub is IBridgehub, ReentrancyGuard, Ownable2StepUpgradeable, Paus
emit StateTransitionManagerRemoved(_stateTransitionManager);
}

/// @notice token can be any contract with the appropriate interface/functionality
/// @param _token address of base token to be registered
function addToken(address _token) external onlyOwner {
require(!tokenIsRegistered[_token], "BH: token already registered");
tokenIsRegistered[_token] = true;
/// @notice To set shared bridge, only Owner. Not done in initialize, as
/// the order of deployment is Bridgehub, Shared bridge, and then we call this
function setSharedBridge(address _sharedBridge) external onlyOwner {
Raid5594 marked this conversation as resolved.
Show resolved Hide resolved
sharedBridge = IL1AssetRouter(_sharedBridge);

emit TokenRegistered(_token);
emit SharedBridgeUpdated(_sharedBridge);
}

/// @notice Used to register a chain as a settlement layer.
Expand Down Expand Up @@ -236,15 +237,15 @@ contract Bridgehub is IBridgehub, ReentrancyGuard, Ownable2StepUpgradeable, Paus
/// @notice for Eth the baseToken address is 1
/// @param _chainId the chainId of the chain
/// @param _stateTransitionManager the state transition manager address
/// @param _baseToken the base token of the chain
/// @param _baseTokenAssetId the base token asset id of the chain
/// @param _salt the salt for the chainId, currently not used
/// @param _admin the admin of the chain
/// @param _initData the fixed initialization data for the chain
/// @param _factoryDeps the factory dependencies for the chain's deployment
function createNewChain(
uint256 _chainId,
address _stateTransitionManager,
address _baseToken,
bytes32 _baseTokenAssetId,
// solhint-disable-next-line no-unused-vars
uint256 _salt,
address _admin,
Expand All @@ -257,21 +258,18 @@ contract Bridgehub is IBridgehub, ReentrancyGuard, Ownable2StepUpgradeable, Paus
require(_chainId != block.chainid, "BH: chain id must not match current chainid");

require(stateTransitionManagerIsRegistered[_stateTransitionManager], "BH: state transition not registered");
require(tokenIsRegistered[_baseToken], "BH: token not registered");
require(address(sharedBridge) != address(0), "BH: shared bridge not set");

require(stateTransitionManager[_chainId] == address(0), "BH: chainId already registered");

stateTransitionManager[_chainId] = _stateTransitionManager;
baseToken[_chainId] = _baseToken;

/// For now all base tokens have to use the NTV.
baseTokenAssetId[_chainId] = DataEncoding.encodeNTVAssetId(block.chainid, _baseToken);
baseTokenAssetId[_chainId] = _baseTokenAssetId;
settlementLayer[_chainId] = block.chainid;

IStateTransitionManager(_stateTransitionManager).createNewChain({
_chainId: _chainId,
_baseToken: _baseToken,
_baseTokenAssetId: _baseTokenAssetId,
_sharedBridge: address(sharedBridge),
_admin: _admin,
_initData: _initData,
Expand All @@ -287,6 +285,12 @@ contract Bridgehub is IBridgehub, ReentrancyGuard, Ownable2StepUpgradeable, Paus
Getters
//////////////////////////////////////////////////////////////*/

// baseToken function, which takes assetId as input, reads assetHandler from AR, and tokenAddress from AH
function baseToken(bytes32 _baseTokenAssetId) public view returns (address) {
address assetHandlerAddress = sharedBridge.assetHandlerAddress(_baseTokenAssetId);
return IL1NativeTokenVault(assetHandlerAddress).tokenAddress(_baseTokenAssetId);
Raid5594 marked this conversation as resolved.
Show resolved Hide resolved
}

/// @notice return the state transition chain contract for a chainId
function getHyperchain(uint256 _chainId) public view returns (address) {
return IStateTransitionManager(stateTransitionManager[_chainId]).getHyperchain(_chainId);
Expand Down
10 changes: 2 additions & 8 deletions l1-contracts/contracts/bridgehub/IBridgehub.sol
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,7 @@ interface IBridgehub is IL1AssetHandler {

function stateTransitionManager(uint256 _chainId) external view returns (address);

function tokenIsRegistered(address _baseToken) external view returns (bool);

function baseToken(uint256 _chainId) external view returns (address);
function baseToken(bytes32 _baseTokenAssetId) external view returns (address);

function baseTokenAssetId(uint256 _chainId) external view returns (bytes32);

Expand Down Expand Up @@ -133,7 +131,7 @@ interface IBridgehub is IL1AssetHandler {
function createNewChain(
uint256 _chainId,
address _stateTransitionManager,
address _baseToken,
bytes32 _baseTokenAssetId,
uint256 _salt,
address _admin,
bytes calldata _initData,
Expand All @@ -144,8 +142,6 @@ interface IBridgehub is IL1AssetHandler {

function removeStateTransitionManager(address _stateTransitionManager) external;

function addToken(address _token) external;

function setAddresses(
address _sharedBridge,
ISTMDeploymentTracker _stmDeployer,
Expand All @@ -158,8 +154,6 @@ interface IBridgehub is IL1AssetHandler {

event StateTransitionManagerRemoved(address indexed stateTransitionManager);

event TokenRegistered(address indexed token);

event SharedBridgeUpdated(address indexed sharedBridge);

function whitelistedSettlementLayers(uint256 _chainId) external view returns (bool);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ contract DummyAdminFacetNoOverlap is ZkSyncHyperchainBase {

function executeUpgradeNoOverlap(Diamond.DiamondCutData calldata _diamondCut) external {
Diamond.diamondCut(_diamondCut);
s.baseTokenAssetId = DataEncoding.encodeNTVAssetId(block.chainid, s.baseToken);
}

function receiveEther() external payable {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ interface IStateTransitionManager {

function createNewChain(
uint256 _chainId,
address _baseToken,
bytes32 _baseTokenAssetId,
address _sharedBridge,
address _admin,
bytes calldata _initData,
Expand Down
24 changes: 15 additions & 9 deletions l1-contracts/contracts/state-transition/StateTransitionManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ contract StateTransitionManager is IStateTransitionManager, ReentrancyGuard, Own
/// @dev deploys a full set of chains contracts
function _deployNewChain(
uint256 _chainId,
address _baseToken,
bytes32 _baseTokenAssetId,
address _sharedBridge,
address _admin,
bytes memory _diamondCut
Expand Down Expand Up @@ -383,7 +383,7 @@ contract StateTransitionManager is IStateTransitionManager, ReentrancyGuard, Own
bytes32(protocolVersion),
bytes32(uint256(uint160(_admin))),
bytes32(uint256(uint160(validatorTimelock))),
bytes32(uint256(uint160(_baseToken))),
_baseTokenAssetId,
bytes32(uint256(uint160(_sharedBridge))),
storedBatchZero
);
Expand All @@ -407,15 +407,15 @@ contract StateTransitionManager is IStateTransitionManager, ReentrancyGuard, Own

/// @notice called by Bridgehub when a chain registers
/// @param _chainId the chain's id
/// @param _baseToken the base token address used to pay for gas fees
/// @param _baseTokenAssetId the base token asset id used to pay for gas fees
/// @param _sharedBridge the shared bridge address, used as base token bridge
/// @param _admin the chain's admin address
/// @param _initData the diamond cut data, force deployments and factoryDeps encoded
/// @param _factoryDeps the factory dependencies used for the genesis upgrade
/// that initializes the chains Diamond Proxy
function createNewChain(
uint256 _chainId,
address _baseToken,
bytes32 _baseTokenAssetId,
address _sharedBridge,
address _admin,
bytes calldata _initData,
Expand All @@ -424,7 +424,7 @@ contract StateTransitionManager is IStateTransitionManager, ReentrancyGuard, Own
(bytes memory _diamondCut, bytes memory _forceDeploymentData) = abi.decode(_initData, (bytes, bytes));

// solhint-disable-next-line func-named-parameters
address hyperchainAddress = _deployNewChain(_chainId, _baseToken, _sharedBridge, _admin, _diamondCut);
address hyperchainAddress = _deployNewChain(_chainId, _baseTokenAssetId, _sharedBridge, _admin, _diamondCut);

{
// check input
Expand Down Expand Up @@ -468,7 +468,13 @@ contract StateTransitionManager is IStateTransitionManager, ReentrancyGuard, Own
address hyperchain = hyperchainMap.get(_chainId);
require(IZkSyncHyperchain(hyperchain).getProtocolVersion() == protocolVersion, "STM: outdated pv");

return abi.encode(IBridgehub(BRIDGE_HUB).baseToken(_chainId), _newGatewayAdmin, protocolVersion, _diamondCut);
return
abi.encode(
IBridgehub(BRIDGE_HUB).baseTokenAssetId(_chainId),
_newGatewayAdmin,
protocolVersion,
_diamondCut
);
}

/// @notice Called by the bridgehub during the migration of a chain to the current settlement layer.
Expand All @@ -478,17 +484,17 @@ contract StateTransitionManager is IStateTransitionManager, ReentrancyGuard, Own
uint256 _chainId,
bytes calldata _stmData
) external override onlyBridgehub returns (address chainAddress) {
(address _baseToken, address _admin, uint256 _protocolVersion, bytes memory _diamondCut) = abi.decode(
(bytes32 _baseTokenAssetId, address _admin, uint256 _protocolVersion, bytes memory _diamondCut) = abi.decode(
_stmData,
(address, address, uint256, bytes)
(bytes32, address, uint256, bytes)
);

// We ensure that the chain has the latest protocol version to avoid edge cases
// related to different protocol version support.
require(_protocolVersion == protocolVersion, "STM, outdated pv");
chainAddress = _deployNewChain({
_chainId: _chainId,
_baseToken: _baseToken,
_baseTokenAssetId: _baseTokenAssetId,
_sharedBridge: address(IBridgehub(BRIDGE_HUB).sharedBridge()),
_admin: _admin,
_diamondCut: _diamondCut
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {Diamond} from "../libraries/Diamond.sol";
import {ZkSyncHyperchainBase} from "./facets/ZkSyncHyperchainBase.sol";
import {L2_TO_L1_LOG_SERIALIZE_SIZE, MAX_GAS_PER_TRANSACTION} from "../../common/Config.sol";
import {InitializeData, IDiamondInit} from "../chain-interfaces/IDiamondInit.sol";
import {IBridgehub} from "../../bridgehub/IBridgehub.sol";
import {PriorityQueue} from "../libraries/PriorityQueue.sol";
import {PriorityTree} from "../libraries/PriorityTree.sol";

Expand All @@ -32,14 +31,14 @@ contract DiamondInit is ZkSyncHyperchainBase, IDiamondInit {
require(_initializeData.priorityTxMaxGasLimit <= MAX_GAS_PER_TRANSACTION, "vu");
require(_initializeData.bridgehub != address(0), "DiamondInit: b0");
require(_initializeData.stateTransitionManager != address(0), "DiamondInit: stm0");
require(_initializeData.baseToken != address(0), "DiamondInit: bt0");
require(_initializeData.baseTokenAssetId != bytes32(0), "DiamondInit: bt0");
require(_initializeData.baseTokenBridge != address(0), "DiamondInit: btb0");
require(_initializeData.blobVersionedHashRetriever != address(0), "DiamondInit: bvhr0");

s.chainId = _initializeData.chainId;
s.bridgehub = _initializeData.bridgehub;
s.stateTransitionManager = _initializeData.stateTransitionManager;
s.baseToken = _initializeData.baseToken;
s.baseTokenAssetId = _initializeData.baseTokenAssetId;
s.baseTokenBridge = _initializeData.baseTokenBridge;
s.protocolVersion = _initializeData.protocolVersion;

Expand All @@ -56,8 +55,6 @@ contract DiamondInit is ZkSyncHyperchainBase, IDiamondInit {
s.blobVersionedHashRetriever = _initializeData.blobVersionedHashRetriever;
s.priorityTree.setup(s.priorityQueue.getTotalPriorityTxs());

s.baseTokenAssetId = IBridgehub(_initializeData.bridgehub).baseTokenAssetId(_initializeData.chainId);

// While this does not provide a protection in the production, it is needed for local testing
// Length of the L2Log encoding should not be equal to the length of other L2Logs' tree nodes preimages
assert(L2_TO_L1_LOG_SERIALIZE_SIZE != 2 * 32);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ struct ZkSyncHyperchainStorage {
/// @dev The address of the StateTransitionManager
address stateTransitionManager;
/// @dev The address of the baseToken contract. Eth is address(1)
address baseToken;
address __DEPRECATED_baseToken;
/// @dev The address of the baseTokenbridge. Eth also uses the shared bridge
address baseTokenBridge;
/// @notice gasPriceMultiplier for each baseToken, so that each L1->L2 transaction pays for its transaction on the destination
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {VerifierParams} from "../../../state-transition/chain-interfaces/IVerifi
import {Diamond} from "../../libraries/Diamond.sol";
import {PriorityQueue} from "../../../state-transition/libraries/PriorityQueue.sol";
import {PriorityTree} from "../../../state-transition/libraries/PriorityTree.sol";
import {IBridgehub} from "../../../bridgehub/IBridgehub.sol";
import {UncheckedMath} from "../../../common/libraries/UncheckedMath.sol";
import {IGetters} from "../../chain-interfaces/IGetters.sol";
import {ILegacyGetters} from "../../chain-interfaces/ILegacyGetters.sol";
Expand Down Expand Up @@ -66,7 +67,14 @@ contract GettersFacet is ZkSyncHyperchainBase, IGetters, ILegacyGetters {

/// @inheritdoc IGetters
function getBaseToken() external view returns (address) {
return s.baseToken;
IBridgehub bridgehub = IBridgehub(s.bridgehub);
bytes32 baseTokenAssetId = bridgehub.baseTokenAssetId(s.chainId);
Raid5594 marked this conversation as resolved.
Show resolved Hide resolved
return bridgehub.baseToken(baseTokenAssetId);
}

/// @inheritdoc IGetters
function getBaseTokenAssetId() external view returns (bytes32) {
return s.baseTokenAssetId;
}

/// @inheritdoc IGetters
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {FeeParams} from "../chain-deps/ZkSyncHyperchainStorage.sol";
/// @param protocolVersion initial protocol version
/// @param validatorTimelock address of the validator timelock that delays execution
/// @param admin address who can manage the contract
/// @param baseToken address of the base token of the chain
/// @param baseTokenAssetId asset id of the base token of the chain
/// @param baseTokenBridge address of the L1 shared bridge contract
/// @param storedBatchZero hash of the initial genesis batch
/// @param verifier address of Verifier contract
Expand All @@ -29,7 +29,7 @@ struct InitializeData {
uint256 protocolVersion;
address admin;
address validatorTimelock;
address baseToken;
bytes32 baseTokenAssetId;
address baseTokenBridge;
bytes32 storedBatchZero;
IVerifier verifier;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ interface IGetters is IZkSyncHyperchainBase {
/// @return The address of the base token
function getBaseToken() external view returns (address);

/// @return The address of the base token
function getBaseTokenAssetId() external view returns (bytes32);

/// @return The address of the base token bridge
function getBaseTokenBridge() external view returns (address);

Expand Down
1 change: 0 additions & 1 deletion l1-contracts/deploy-scripts/DeployL1.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -666,7 +666,6 @@ contract DeployL1Script is Script {
function registerSharedBridge() internal {
Bridgehub bridgehub = Bridgehub(addresses.bridgehub.bridgehubProxy);
vm.startBroadcast(msg.sender);
bridgehub.addToken(ADDRESS_ONE);
Raid5594 marked this conversation as resolved.
Show resolved Hide resolved
// bridgehub.setSharedBridge(addresses.bridges.sharedBridgeProxy);
bridgehub.setAddresses(
addresses.bridges.sharedBridgeProxy,
Expand Down
25 changes: 3 additions & 22 deletions l1-contracts/deploy-scripts/RegisterHyperchain.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ contract RegisterHyperchainScript is Script {
address validatorSenderOperatorCommitEth;
address validatorSenderOperatorBlobsEth;
address baseToken;
bytes32 baseTokenAssetId;
uint128 baseTokenGasPriceMultiplierNominator;
uint128 baseTokenGasPriceMultiplierDenominator;
address bridgehub;
Expand All @@ -59,7 +60,6 @@ contract RegisterHyperchainScript is Script {
deployGovernance();
deployChainAdmin();
checkTokenAddress();
registerTokenOnBridgehub();
registerTokenOnNTV();
registerHyperchain();
addValidators();
Expand Down Expand Up @@ -128,30 +128,11 @@ contract RegisterHyperchainScript is Script {
console.log("Using base token address:", config.baseToken);
}

function registerTokenOnBridgehub() internal {
Raid5594 marked this conversation as resolved.
Show resolved Hide resolved
IBridgehub bridgehub = IBridgehub(config.bridgehub);
Ownable ownable = Ownable(config.bridgehub);

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(),
_salt: bytes32(config.bridgehubCreateNewChainSalt),
_target: config.bridgehub,
_data: data,
_value: 0,
_delay: 0
});
console.log("Token registered on Bridgehub");
}
}

function registerTokenOnNTV() internal {
IL1NativeTokenVault ntv = IL1NativeTokenVault(config.nativeTokenVault);
// Ownable ownable = Ownable(config.nativeTokenVault);
bytes32 assetId = DataEncoding.encodeNTVAssetId(block.chainid, config.baseToken);
config.baseTokenAssetId = assetId;
if (ntv.tokenAddress(assetId) != address(0)) {
console.log("Token already registered on NTV");
} else {
Expand Down Expand Up @@ -189,7 +170,7 @@ contract RegisterHyperchainScript is Script {
(
config.chainChainId,
config.stateTransitionProxy,
config.baseToken,
config.baseTokenAssetId,
config.bridgehubCreateNewChainSalt,
msg.sender,
abi.encode(config.diamondCutData, config.forceDeployments),
Expand Down
Loading
Loading