Skip to content

Improve gateway registration scripts #1453

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

Open
wants to merge 19 commits into
base: main
Choose a base branch
from
Open
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
6 changes: 3 additions & 3 deletions AllContractsHashes.json
Original file line number Diff line number Diff line change
Expand Up @@ -993,11 +993,11 @@
},
{
"contractName": "l1-contracts/GatewayTransactionFilterer",
"zkBytecodeHash": "0x0100014354128e3401c9aad6e9ed777670005f8b361ed5dd9297b73d87241e83",
"zkBytecodeHash": "0x010001754b7b23b287f0024f1bf59e917d1c3f3a0012b8cf60ec22b72e38613f",
"zkBytecodePath": "/l1-contracts/zkout/GatewayTransactionFilterer.sol/GatewayTransactionFilterer.json",
"evmBytecodeHash": "0x6f2f2c53b94a8fb5ed02f991755a67fb0e993c4cc9c4bc9b426bf9a55303e08e",
"evmBytecodeHash": "0xba0d07351ed53f8aa3a2de299e7dba066cebeb8b3a77edcf7f75e68944531681",
"evmBytecodePath": "/l1-contracts/out/GatewayTransactionFilterer.sol/GatewayTransactionFilterer.json",
"evmDeployedBytecodeHash": "0x730d6270c95308e35240ed63edead5d2956149488c5e25ad83c7e4a7f3bb4af1"
"evmDeployedBytecodeHash": "0xf6a9180339268ef70faca00fb48f38bc2984d364d0269b1dda5059d6c3835721"
},
{
"contractName": "l1-contracts/GatewayUpgrade",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@ import {IBridgehub} from "../bridgehub/IBridgehub.sol";
import {IAssetRouterBase} from "../bridge/asset-router/IAssetRouterBase.sol";
import {IL2AssetRouter} from "../bridge/asset-router/IL2AssetRouter.sol";

/// @dev The errors below are written here instead of a dedicate file to avoid
/// source code changes to another contracts.y
// 0x55ccf3e4
error NotBlocklisted(address);
// 0x7b0b7f4f
error AlreadyBlocklisted(address);

/// @dev We want to ensure that only whitelisted contracts can ever be deployed,
/// while allowing anyone to call any other method. Thus, we disallow calls that can deploy contracts
/// (i.e. calls to the predeployed Create2Factory or ContractDeployer).
Expand All @@ -27,15 +34,24 @@ contract GatewayTransactionFilterer is ITransactionFilterer, Ownable2StepUpgrade
/// @notice Event emitted when sender is removed from whitelist
event WhitelistRevoked(address indexed sender);

/// @notice Event emitted when contract is blocklisted
event Blocklisted(address indexed l2Contract);

/// @notice Event emitted when contract is removed from blocklist
event RemovedFromBlocklist(address indexed l2Contract);

/// @notice The ecosystem's Bridgehub
IBridgehub public immutable BRIDGE_HUB;

/// @notice The L1 asset router
address public immutable L1_ASSET_ROUTER;

/// @notice Indicates whether the sender is whitelisted to deposit to Gateway
/// @notice Indicates whether the sender is allowed to call any contract on Gateway
mapping(address sender => bool whitelisted) public whitelistedSenders;

/// @notice Indicates whether the l2Contract is blacklisted from being called via L1->L2 transactions.
mapping(address l2Contract => bool blocklisted) public blocklistedContracts;

/// @dev Contract is expected to be used as proxy implementation.
/// @dev Initialize the implementation to prevent Parity hack.
constructor(IBridgehub _bridgeHub, address _assetRouter) {
Expand Down Expand Up @@ -73,6 +89,27 @@ contract GatewayTransactionFilterer is ITransactionFilterer, Ownable2StepUpgrade
emit WhitelistRevoked(sender);
}

/// @notice Blocklist an L2 contract
/// @param _l2Contract The contract to blocklist
function blocklistL2Contract(address _l2Contract) external onlyOwner {
if (blocklistedContracts[_l2Contract]) {
revert AlreadyBlocklisted(_l2Contract);
}
blocklistedContracts[_l2Contract] = true;

emit Blocklisted(_l2Contract);
}

/// @notice Removes an L2 contract from the blocklist
/// @param _l2Contract The contract to remote from the blocklist
function removeFromBlocklist(address _l2Contract) external onlyOwner {
if (!blocklistedContracts[_l2Contract]) {
revert NotBlocklisted(_l2Contract);
}
blocklistedContracts[_l2Contract] = false;
emit RemovedFromBlocklist(_l2Contract);
}

/// @notice Checks if the transaction is allowed
/// @param sender The sender of the transaction
/// @param l2Calldata The calldata of the L2 transaction
Expand Down Expand Up @@ -101,6 +138,10 @@ contract GatewayTransactionFilterer is ITransactionFilterer, Ownable2StepUpgrade
return _checkCTMAssetId(decodedAssetId);
}

if (blocklistedContracts[contractL2]) {
return false;
}

// We always allow calls to the L2AssetRouter contract. We expect that it will not
// cause deploying of any unwhitelisted code, but it is needed to facilitate withdrawals of chains.
if (contractL2 > MIN_ALLOWED_ADDRESS || contractL2 == L2_ASSET_ROUTER_ADDR) {
Expand Down
39 changes: 3 additions & 36 deletions l1-contracts/deploy-scripts/Create2FactoryUtils.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {Script, console2 as console} from "forge-std/Script.sol";
import {Utils} from "./Utils.sol";
import {Create2AndTransfer} from "./Create2AndTransfer.sol";
import {AddressHasNoCode} from "./ZkSyncScriptErrors.sol";
import {DeploymentNotifier} from "./DeploymentNotifier.sol";

/// @title Create2FactoryUtils
/// @notice This abstract contract encapsulates all Create2Factory processing logic,
Expand Down Expand Up @@ -165,7 +166,7 @@ abstract contract Create2FactoryUtils is Script {
string memory contractName,
bytes memory constructorParams
) internal {
notifyAboutDeployment(contractAddr, contractName, constructorParams, contractName);
DeploymentNotifier.notifyAboutDeployment(contractAddr, contractName, constructorParams, false);
}

/// @notice Notifies about a deployment by printing messages to the console.
Expand All @@ -180,41 +181,7 @@ abstract contract Create2FactoryUtils is Script {
bytes memory constructorParams,
string memory displayName
) internal {
string memory basicMessage = string.concat(displayName, " has been deployed at ", vm.toString(contractAddr));
console.log(basicMessage);

string memory deployedContractName = getDeployedContractName(contractName);
string memory forgeMessage;
if (constructorParams.length == 0) {
forgeMessage = string.concat(
"forge verify-contract ",
vm.toString(contractAddr),
" ",
deployedContractName
);
} else {
forgeMessage = string.concat(
"forge verify-contract ",
vm.toString(contractAddr),
" ",
deployedContractName,
" --constructor-args ",
vm.toString(constructorParams)
);
}
console.log(forgeMessage);
}

/// @notice Returns the deployed contract name.
/// This function can be modified if the deployed name should differ from the internal name.
/// @param contractName The internal name of the contract.
/// @return The name to be used for verification.
function getDeployedContractName(string memory contractName) internal view virtual returns (string memory) {
if (compareStrings(contractName, "BridgedTokenBeacon")) {
return "UpgradeableBeacon";
} else {
return contractName;
}
DeploymentNotifier.notifyAboutDeployment(contractAddr, contractName, constructorParams, displayName, false);
}

/// @notice Compares two strings for equality.
Expand Down
1 change: 1 addition & 0 deletions l1-contracts/deploy-scripts/DeployUtils.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ struct Config {
address deployerAddress;
uint256 eraChainId;
address ownerAddress;
address adminAddress;
bool testnetVerifier;
bool supportL2LegacySharedBridgeTest;
ContractsConfig contracts;
Expand Down
68 changes: 68 additions & 0 deletions l1-contracts/deploy-scripts/DeploymentNotifier.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

import {Vm} from "forge-std/Vm.sol";
import {Script, console2 as console} from "forge-std/Script.sol";

/// @title DeploymentNotifier
/// @notice A library to handle console notifications and forge verification messages
library DeploymentNotifier {
address internal constant VM_ADDRESS = address(uint160(uint256(keccak256("hevm cheat code"))));
Vm internal constant vm = Vm(VM_ADDRESS);

/// @notice Notify about a deployment using the contractName as displayName
function notifyAboutDeployment(
address contractAddr,
string memory contractName,
bytes memory constructorParams,
bool isZKBytecode
) internal pure {
notifyAboutDeployment(contractAddr, contractName, constructorParams, contractName, isZKBytecode);
}

/// @notice Notify about a deployment with a custom displayName
function notifyAboutDeployment(
address contractAddr,
string memory contractName,
bytes memory constructorParams,
string memory displayName,
bool isZKBytecode
) internal pure {
// Basic console message
string memory basicMessage = string.concat(displayName, " has been deployed at ", vm.toString(contractAddr));
console.log(basicMessage);

// Forge verification command
string memory deployedName = getDeployedContractName(contractName);
string memory forgeCmd = "forge verify-contract ";
if (isZKBytecode) {
forgeCmd = string.concat(forgeCmd, "--zksync ");
}
if (constructorParams.length == 0) {
forgeCmd = string.concat(forgeCmd, vm.toString(contractAddr), " ", deployedName);
} else {
forgeCmd = string.concat(
forgeCmd,
vm.toString(contractAddr),
" ",
deployedName,
" --constructor-args ",
vm.toString(constructorParams)
);
}
console.log(forgeCmd);
}

/// @notice Map certain contract names to their verification target names
function getDeployedContractName(string memory contractName) internal pure returns (string memory) {
if (compareStrings(contractName, "BridgedTokenBeacon")) {
return "UpgradeableBeacon";
}
return contractName;
}

/// @notice Compare two strings for equality
function compareStrings(string memory a, string memory b) internal pure returns (bool) {
return keccak256(abi.encodePacked(a)) == keccak256(abi.encodePacked(b));
}
}
Loading
Loading