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

(feat): add tx filterer contract #772

Merged
merged 21 commits into from
Sep 10, 2024
Merged
4 changes: 4 additions & 0 deletions l1-contracts/contracts/common/L1ContractErrors.sol
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ error AddressAlreadyUsed(address addr);
error AddressHasNoCode(address);
// 0x1eee5481
error AddressTooLow(address);
// 0x0bfcef28
error AlreadyWhitelisted(address);
// 0x6afd6c20
error BadReturnData();
// 0x6ef9a972
Expand Down Expand Up @@ -193,6 +195,8 @@ error NonZeroAddress(address);
error NotEnoughGas();
// 0xdd7e3621
error NotInitializedReentrancyGuard();
// 0xdf17e316
error NotWhitelisted(address);
// 0xf3ed9dfa
error OnlyEraSupported();
// 0x1a21feed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,11 @@ contract GettersFacet is ZKChainBase, IGetters, ILegacyGetters {
return s.totalBatchesExecuted;
}

/// @inheritdoc IGetters
function getTransactionFilterer() external view returns (address) {
return s.transactionFilterer;
}

/// @inheritdoc IGetters
function getTotalPriorityTxs() external view returns (uint256) {
return _getTotalPriorityTxs();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ interface IGetters is IZKChainBase {
/// @return The total number of batches that were committed & verified & executed
function getTotalBatchesExecuted() external view returns (uint256);

// @return Address of transaction filterer
function getTransactionFilterer() external view returns (address);

/// @return The total number of priority operations that were added to the priority queue, including all processed ones
function getTotalPriorityTxs() external view returns (uint256);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// SPDX-License-Identifier: MIT

pragma solidity 0.8.24;

import {Ownable2StepUpgradeable} from "@openzeppelin/contracts-upgradeable-v4/access/Ownable2StepUpgradeable.sol";

import {ReentrancyGuard} from "../common/ReentrancyGuard.sol";
import {AlreadyWhitelisted, InvalidSelector, NotWhitelisted, ZeroAddress} from "../common/L1ContractErrors.sol";
import {ITransactionFilterer} from "../state-transition/chain-interfaces/ITransactionFilterer.sol";
import {IBridgehub} from "../bridgehub/IBridgehub.sol";
import {IL2Bridge} from "../bridge/interfaces/IL2Bridge.sol";

/// @author Matter Labs
/// @custom:security-contact security@matterlabs.dev
/// @dev Filters transactions received by the Mailbox
/// @dev Only allows whitelisted senders to deposit to Gateway
contract GatewayTransactionFilterer is ITransactionFilterer, ReentrancyGuard, Ownable2StepUpgradeable {
/// @notice Event emitted when sender is whitelisted
event WhitelistGranted(address indexed sender);

/// @notice Event emitted when sender is removed from whitelist
event WhitelistRevoked(address indexed sender);

/// @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
mapping(address sender => bool whitelisted) public whitelistedSenders;

/// @dev Contract is expected to be used as proxy implementation.
/// @dev Initialize the implementation to prevent Parity hack.
constructor(IBridgehub _bridgeHub, address _assetRouter) reentrancyGuardInitializer {
BRIDGE_HUB = _bridgeHub;
L1_ASSET_ROUTER = _assetRouter;
_disableInitializers();
}

/// @notice Initializes a contract filterer for later use. Expected to be used in the proxy.
/// @param _owner The address which can upgrade the implementation.
function initialize(address _owner) external reentrancyGuardInitializer initializer {
if (_owner == address(0)) {
revert ZeroAddress();
}
_transferOwnership(_owner);
}

/// @notice Whitelists the sender.
/// @param sender Address of the tx sender.
function grantWhitelist(address sender) external onlyOwner {
if (whitelistedSenders[sender]) {
revert AlreadyWhitelisted(sender);
}
whitelistedSenders[sender] = true;
emit WhitelistGranted(sender);
}

/// @notice Revoke the sender from whitelist.
/// @param sender Address of the tx sender.
function revokeWhitelist(address sender) external onlyOwner {
if (!whitelistedSenders[sender]) {
revert NotWhitelisted(sender);
}
whitelistedSenders[sender] = false;
emit WhitelistRevoked(sender);
}

/// @notice Checks if the transaction is allowed
/// @param sender The sender of the transaction
/// @param l2Calldata The calldata of the L2 transaction
/// @return Whether the transaction is allowed
function isTransactionAllowed(
address sender,
address,
uint256,
uint256,
bytes calldata l2Calldata,
address
) external view returns (bool) {
if (sender == L1_ASSET_ROUTER) {
bytes4 l2TxSelector = bytes4(l2Calldata[:4]);
if (IL2Bridge.finalizeDeposit.selector != l2TxSelector) {
revert InvalidSelector(l2TxSelector);
}

(bytes32 decodedAssetId, ) = abi.decode(l2Calldata[4:], (bytes32, bytes));
address stmAddress = BRIDGE_HUB.ctmAssetIdToAddress(decodedAssetId);
return (stmAddress != address(0));
}

return whitelistedSenders[sender];
}
}
34 changes: 29 additions & 5 deletions l1-contracts/deploy-scripts/Gateway.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@ import {Script, console2 as console} from "forge-std/Script.sol";
// import {Vm} from "forge-std/Vm.sol";
import {stdToml} from "forge-std/StdToml.sol";

import {TransparentUpgradeableProxy} from "@openzeppelin/contracts-v4/proxy/transparent/TransparentUpgradeableProxy.sol";

import {Ownable} from "@openzeppelin/contracts-v4/access/Ownable.sol";
import {IBridgehub, BridgehubBurnCTMAssetData} from "contracts/bridgehub/IBridgehub.sol";
import {IZKChain} from "contracts/state-transition/chain-interfaces/IZKChain.sol";
import {GatewayTransactionFilterer} from "contracts/transactionFilterer/GatewayTransactionFilterer.sol";
// import {ValidatorTimelock} from "contracts/state-transition/ValidatorTimelock.sol";
// import {Governance} from "contracts/governance/Governance.sol";
// import {Utils} from "./Utils.sol";
Expand All @@ -21,8 +24,6 @@ import {L2_BRIDGEHUB_ADDR} from "contracts/common/L2ContractAddresses.sol";

// import {IL1AssetRouter} from "contracts/bridge/interfaces/IL1AssetRouter.sol";

import {IZKChain} from "contracts/state-transition/chain-interfaces/IZKChain.sol";

contract GatewayScript is Script {
using stdToml for string;

Expand Down Expand Up @@ -118,9 +119,32 @@ contract GatewayScript is Script {
function registerGateway() public {
IBridgehub bridgehub = IBridgehub(config.bridgehub);
Ownable ownable = Ownable(config.bridgehub);
vm.prank(ownable.owner());
Ownable ownableStmDT = Ownable(config.ctmDeploymentTracker);
IZKChain chainL2 = IZKChain(bridgehub.getZKChain(config.chainChainId));
IZKChain chain = IZKChain(bridgehub.getZKChain(config.gatewayChainId));
vm.startPrank(chain.getAdmin());
GatewayTransactionFilterer transactionFiltererImplementation = new GatewayTransactionFilterer(
IBridgehub(config.bridgehub),
config.sharedBridgeProxy
);
address transactionFiltererProxy = address(
new TransparentUpgradeableProxy(
address(transactionFiltererImplementation),
chain.getAdmin(),
abi.encodeCall(GatewayTransactionFilterer.initialize, ownable.owner())
)
);
chain.setTransactionFilterer(transactionFiltererProxy);
vm.stopPrank();

vm.startPrank(ownable.owner());
GatewayTransactionFilterer(transactionFiltererProxy).grantWhitelist(ownableStmDT.owner());
GatewayTransactionFilterer(transactionFiltererProxy).grantWhitelist(chainL2.getAdmin());
GatewayTransactionFilterer(transactionFiltererProxy).grantWhitelist(config.sharedBridgeProxy);
bridgehub.registerSettlementLayer(config.gatewayChainId, true);
// bytes memory data = abi.encodeCall(ctm.registerSettlementLayer, (config.chainChainId, true));

vm.stopPrank();
// bytes memory data = abi.encodeCall(stm.registerSettlementLayer, (config.chainChainId, true));
// Utils.executeUpgrade({
// _governor: ownable.owner(),
// _salt: bytes32(config.bridgehubCreateNewChainSalt),
Expand Down Expand Up @@ -183,7 +207,7 @@ contract GatewayScript is Script {
function registerL2Contracts() public {
IBridgehub bridgehub = IBridgehub(config.bridgehub);
Ownable ownable = Ownable(config.ctmDeploymentTracker);
// IChainTypeManager ctm = IChainTypeManager(config.stateTransitionProxy);
// IStateTransitionManager stm = IStateTransitionManager(config.stateTransitionProxy);

uint256 gasPrice = 10;
uint256 l2GasLimit = 72000000;
Expand Down
1 change: 1 addition & 0 deletions l1-contracts/src.ts/deploy-test-process.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ export async function initialTestnetDeploymentProcess(
await initialBridgehubDeployment(deployer, extraFacets, gasPrice, false);
await registerZKChainWithBridgeRegistration(deployer, false, extraFacets, gasPrice, baseTokenName);
await registerTestDAValidators(deployer);

return deployer;
}

Expand Down
Loading
Loading