Skip to content

Commit

Permalink
Merge branch 'dev' into denis/dev_func_args_4
Browse files Browse the repository at this point in the history
  • Loading branch information
dnkolegov committed Mar 22, 2024
2 parents a0df49e + 90fa37f commit c5fca0c
Show file tree
Hide file tree
Showing 91 changed files with 564 additions and 545 deletions.
48 changes: 30 additions & 18 deletions l1-contracts/contracts/bridge/L1SharedBridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {L2Message, TxStatus} from "../common/Messaging.sol";
import {UnsafeBytes} from "../common/libraries/UnsafeBytes.sol";
import {ReentrancyGuard} from "../common/ReentrancyGuard.sol";
import {AddressAliasHelper} from "../vendor/AddressAliasHelper.sol";
import {ERA_CHAIN_ID, ERA_ERC20_BRIDGE_ADDRESS, ETH_TOKEN_ADDRESS, ERA_DIAMOND_PROXY, TWO_BRIDGES_MAGIC_VALUE} from "../common/Config.sol";
import {ETH_TOKEN_ADDRESS, TWO_BRIDGES_MAGIC_VALUE} from "../common/Config.sol";
import {IBridgehub, L2TransactionRequestTwoBridgesInner, L2TransactionRequestDirect} from "../bridgehub/IBridgehub.sol";
import {IGetters} from "../state-transition/chain-interfaces/IGetters.sol";
import {L2_BASE_TOKEN_SYSTEM_CONTRACT_ADDR} from "../common/L2ContractAddresses.sol";
Expand All @@ -39,6 +39,15 @@ contract L1SharedBridge is IL1SharedBridge, ReentrancyGuard, Initializable, Owna
/// @dev Legacy bridge smart contract that used to hold ERC20 tokens.
IL1ERC20Bridge public immutable override legacyBridge;

Check warning on line 40 in l1-contracts/contracts/bridge/L1SharedBridge.sol

View workflow job for this annotation

GitHub Actions / lint

Immutable variables name are set to be in capitalized SNAKE_CASE

Check warning on line 40 in l1-contracts/contracts/bridge/L1SharedBridge.sol

View workflow job for this annotation

GitHub Actions / lint

Immutable variables name are set to be in capitalized SNAKE_CASE

Check warning on line 40 in l1-contracts/contracts/bridge/L1SharedBridge.sol

View workflow job for this annotation

GitHub Actions / lint

Immutable variables name are set to be in capitalized SNAKE_CASE

/// @dev Era's chainID
uint256 immutable eraChainId;

/// @dev The address of legacy L1 ERC20 bridge.
address immutable eraErc20BridgeAddress;

/// @dev The address of zkSync Era diamond proxy contract.
address immutable eraDiamondProxy;

/// @dev Stores the first batch number on the zkSync Era Diamond Proxy that was settled after Shared Bridge upgrade.
/// This variable is used to differentiate between pre-upgrade and post-upgrade withdrawals. Withdrawals from batches older
/// than this value are considered to have been finalized prior to the upgrade and handled separately.
Expand Down Expand Up @@ -73,7 +82,7 @@ contract L1SharedBridge is IL1SharedBridge, ReentrancyGuard, Initializable, Owna
/// @notice Checks that the message sender is the bridgehub or zkSync Era Diamond Proxy.
modifier onlyBridgehubOrEra(uint256 _chainId) {
require(
msg.sender == address(bridgehub) || (_chainId == ERA_CHAIN_ID && msg.sender == ERA_DIAMOND_PROXY),
msg.sender == address(bridgehub) || (_chainId == eraChainId && msg.sender == eraDiamondProxy),
"L1SharedBridge: not bridgehub or era chain"
);
_;
Expand All @@ -90,12 +99,18 @@ contract L1SharedBridge is IL1SharedBridge, ReentrancyGuard, Initializable, Owna
constructor(
address _l1WethAddress,
IBridgehub _bridgehub,
IL1ERC20Bridge _legacyBridge
IL1ERC20Bridge _legacyBridge,
uint256 _eraChainId,
address _eraErc20BridgeAddress,
address _eraDiamondProxy
) reentrancyGuardInitializer {
_disableInitializers();
l1WethAddress = _l1WethAddress;
bridgehub = _bridgehub;
legacyBridge = _legacyBridge;
eraChainId = _eraChainId;
eraErc20BridgeAddress = _eraErc20BridgeAddress;
eraDiamondProxy = _eraDiamondProxy;
}

/// @dev Initializes a contract bridge for later use. Expected to be used in the proxy
Expand All @@ -109,7 +124,7 @@ contract L1SharedBridge is IL1SharedBridge, ReentrancyGuard, Initializable, Owna
_transferOwnership(_owner);

eraFirstPostUpgradeBatch = _eraFirstPostUpgradeBatch;
l2BridgeAddress[ERA_CHAIN_ID] = ERA_ERC20_BRIDGE_ADDRESS;
l2BridgeAddress[eraChainId] = eraErc20BridgeAddress;
}

/// @dev transfer tokens from legacy erc20 bridge or mailbox and set chainBalance as part of migration process
Expand Down Expand Up @@ -380,7 +395,7 @@ contract L1SharedBridge is IL1SharedBridge, ReentrancyGuard, Initializable, Owna
/// @param _l2BatchNumber The L2 batch number for the withdrawal.
/// @return Whether withdrawal was initiated on zkSync Era before Shared Bridge upgrade.
function _isEraLegacyWithdrawal(uint256 _chainId, uint256 _l2BatchNumber) internal view returns (bool) {
return (_chainId == ERA_CHAIN_ID) && (_l2BatchNumber < eraFirstPostUpgradeBatch);
return (_chainId == eraChainId) && (_l2BatchNumber < eraFirstPostUpgradeBatch);
}

/// @notice Finalize the withdrawal and release funds
Expand Down Expand Up @@ -435,10 +450,7 @@ contract L1SharedBridge is IL1SharedBridge, ReentrancyGuard, Initializable, Owna
// Handling special case for withdrawal from zkSync Era initiated before Shared Bridge.
if (_isEraLegacyWithdrawal(_chainId, _l2BatchNumber)) {
// Checks that the withdrawal wasn't finalized already.
bool alreadyFinalized = IGetters(ERA_DIAMOND_PROXY).isEthWithdrawalFinalized(
_l2BatchNumber,
_l2MessageIndex
);
bool alreadyFinalized = IGetters(eraDiamondProxy).isEthWithdrawalFinalized(_l2BatchNumber, _l2MessageIndex);
require(!alreadyFinalized, "Withdrawal is already finalized 2");
}

Expand Down Expand Up @@ -575,12 +587,12 @@ contract L1SharedBridge is IL1SharedBridge, ReentrancyGuard, Initializable, Owna
uint256 _l2TxGasPerPubdataByte,
address _refundRecipient
) external payable override onlyLegacyBridge nonReentrant returns (bytes32 l2TxHash) {
require(l2BridgeAddress[ERA_CHAIN_ID] != address(0), "ShB b. n dep");
require(l2BridgeAddress[eraChainId] != address(0), "ShB b. n dep");
require(_l1Token != l1WethAddress, "ShB: WETH deposit not supported 2");

// Note that funds have been transferred to this contract in the legacy ERC20 bridge.
if (!hyperbridgingEnabled[ERA_CHAIN_ID]) {
chainBalance[ERA_CHAIN_ID][_l1Token] += _amount;
if (!hyperbridgingEnabled[eraChainId]) {
chainBalance[eraChainId][_l1Token] += _amount;
}

bytes memory l2TxCalldata = _getDepositL2Calldata(_prevMsgSender, _l2Receiver, _l1Token, _amount);
Expand All @@ -597,8 +609,8 @@ contract L1SharedBridge is IL1SharedBridge, ReentrancyGuard, Initializable, Owna
}

L2TransactionRequestDirect memory request = L2TransactionRequestDirect({
chainId: ERA_CHAIN_ID,
l2Contract: l2BridgeAddress[ERA_CHAIN_ID],
chainId: eraChainId,
l2Contract: l2BridgeAddress[eraChainId],
mintValue: msg.value, // l2 gas + l2 msg.Value the bridgehub will withdraw the mintValue from the base token bridge for gas
l2Value: 0, // L2 msg.value, this contract doesn't support base token deposits or wrapping functionality, for direct deposits use bridgehub
l2Calldata: l2TxCalldata,
Expand All @@ -612,10 +624,10 @@ contract L1SharedBridge is IL1SharedBridge, ReentrancyGuard, Initializable, Owna

bytes32 txDataHash = keccak256(abi.encode(_prevMsgSender, _l1Token, _amount));
// Save the deposited amount to claim funds on L1 if the deposit failed on L2
depositHappened[ERA_CHAIN_ID][l2TxHash] = txDataHash;
depositHappened[eraChainId][l2TxHash] = txDataHash;

emit LegacyDepositInitiated({
chainId: ERA_CHAIN_ID,
chainId: eraChainId,
l2DepositTxHash: l2TxHash,
from: _prevMsgSender,
to: _l2Receiver,
Expand All @@ -642,7 +654,7 @@ contract L1SharedBridge is IL1SharedBridge, ReentrancyGuard, Initializable, Owna
bytes32[] calldata _merkleProof
) external override onlyLegacyBridge returns (address l1Receiver, address l1Token, uint256 amount) {
(l1Receiver, l1Token, amount) = _finalizeWithdrawal({
_chainId: ERA_CHAIN_ID,
_chainId: eraChainId,
_l2BatchNumber: _l2BatchNumber,
_l2MessageIndex: _l2MessageIndex,
_l2TxNumberInBatch: _l2TxNumberInBatch,
Expand Down Expand Up @@ -675,7 +687,7 @@ contract L1SharedBridge is IL1SharedBridge, ReentrancyGuard, Initializable, Owna
) external override onlyLegacyBridge {
_claimFailedDeposit({
_checkedInLegacyBridge: true,
_chainId: ERA_CHAIN_ID,
_chainId: eraChainId,
_depositSender: _depositSender,
_l1Token: _l1Token,
_amount: _amount,
Expand Down
32 changes: 13 additions & 19 deletions l1-contracts/contracts/common/Config.sol
Original file line number Diff line number Diff line change
Expand Up @@ -47,35 +47,35 @@ uint256 constant COMMIT_TIMESTAMP_APPROXIMATION_DELTA = 1 hours;
uint256 constant PUBLIC_INPUT_SHIFT = 32;

/// @dev The maximum number of L2 gas that a user can request for an L2 transaction
uint256 constant MAX_GAS_PER_TRANSACTION = $(MAX_GAS_PER_TRANSACTION);
uint256 constant MAX_GAS_PER_TRANSACTION = 80_000_000;

/// @dev Even though the price for 1 byte of pubdata is 16 L1 gas, we have a slightly increased
/// value.
uint256 constant L1_GAS_PER_PUBDATA_BYTE = $(L1_GAS_PER_PUBDATA_BYTE);
uint256 constant L1_GAS_PER_PUBDATA_BYTE = 17;

/// @dev The intrinsic cost of the L1->l2 transaction in computational L2 gas
uint256 constant L1_TX_INTRINSIC_L2_GAS = $(L1_TX_INTRINSIC_L2_GAS);
uint256 constant L1_TX_INTRINSIC_L2_GAS = 167_157;

/// @dev The intrinsic cost of the L1->l2 transaction in pubdata
uint256 constant L1_TX_INTRINSIC_PUBDATA = $(L1_TX_INTRINSIC_PUBDATA);
uint256 constant L1_TX_INTRINSIC_PUBDATA = 88;

/// @dev The minimal base price for L1 transaction
uint256 constant L1_TX_MIN_L2_GAS_BASE = $(L1_TX_MIN_L2_GAS_BASE);
uint256 constant L1_TX_MIN_L2_GAS_BASE = 173_484;

/// @dev The number of L2 gas the transaction starts costing more with each 544 bytes of encoding
uint256 constant L1_TX_DELTA_544_ENCODING_BYTES = $(L1_TX_DELTA_544_ENCODING_BYTES);
uint256 constant L1_TX_DELTA_544_ENCODING_BYTES = 1656;

/// @dev The number of L2 gas an L1->L2 transaction gains with each new factory dependency
uint256 constant L1_TX_DELTA_FACTORY_DEPS_L2_GAS = $(L1_TX_DELTA_FACTORY_DEPS_L2_GAS);
uint256 constant L1_TX_DELTA_FACTORY_DEPS_L2_GAS = 2473;

/// @dev The number of L2 gas an L1->L2 transaction gains with each new factory dependency
uint256 constant L1_TX_DELTA_FACTORY_DEPS_PUBDATA = $(L1_TX_DELTA_FACTORY_DEPS_PUBDATA);
uint256 constant L1_TX_DELTA_FACTORY_DEPS_PUBDATA = 64;

/// @dev The number of pubdata an L1->L2 transaction requires with each new factory dependency
uint256 constant MAX_NEW_FACTORY_DEPS = $(MAX_NEW_FACTORY_DEPS);
uint256 constant MAX_NEW_FACTORY_DEPS = 32;

/// @dev The L2 gasPricePerPubdata required to be used in bridges.
uint256 constant REQUIRED_L2_GAS_PRICE_PER_PUBDATA = $(REQUIRED_L2_GAS_PRICE_PER_PUBDATA);
uint256 constant REQUIRED_L2_GAS_PRICE_PER_PUBDATA = 800;

/// @dev The mask which should be applied to the packed batch and L2 block timestamp in order
/// to obtain the L2 block timestamp. Applying this mask is equivalent to calculating modulo 2**128
Expand All @@ -98,16 +98,10 @@ uint256 constant TX_SLOT_OVERHEAD_L2_GAS = 10000;
/// the operator in case the batch is closed because of the memory for transactions being filled up.
uint256 constant MEMORY_OVERHEAD_GAS = 10;

address constant ETH_TOKEN_ADDRESS = address(1);

/// @dev Era's chainID
uint256 constant ERA_CHAIN_ID = $(ERA_CHAIN_ID);
/// @dev The maximum gas limit for a priority transaction in L2.
uint256 constant PRIORITY_TX_MAX_GAS_LIMIT = 72_000_000;

/// @dev The address of legacy L1 ERC20 bridge.
address constant ERA_ERC20_BRIDGE_ADDRESS = $(ERA_ERC20_BRIDGE_ADDRESS);

/// @dev The address of zkSync Era diamond proxy contract.
address constant ERA_DIAMOND_PROXY = $(ERA_DIAMOND_PROXY);
address constant ETH_TOKEN_ADDRESS = address(1);

bytes32 constant TWO_BRIDGES_MAGIC_VALUE = bytes32(uint256(keccak256("TWO_BRIDGES_MAGIC_VALUE")) - 1);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {MailboxFacet} from "../../state-transition/chain-deps/facets/Mailbox.sol
import {FeeParams, PubdataPricingMode} from "../../state-transition/chain-deps/ZkSyncStateTransitionStorage.sol";

contract DummyStateTransition is MailboxFacet {
constructor(address bridgeHubAddress) {
constructor(address bridgeHubAddress, uint256 _eraChainId) MailboxFacet(_eraChainId) {
s.bridgehub = bridgeHubAddress;
}

Expand Down
23 changes: 15 additions & 8 deletions l1-contracts/contracts/dev-contracts/test/L1SharedBridgeTest.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,35 @@ import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";

import {L1SharedBridge} from "../../bridge/L1SharedBridge.sol";
import {IL1ERC20Bridge, IBridgehub} from "../../bridge/interfaces/IL1SharedBridge.sol";
import {ETH_TOKEN_ADDRESS, ERA_CHAIN_ID} from "../../common/Config.sol";
import {ETH_TOKEN_ADDRESS} from "../../common/Config.sol";

/// @author Matter Labs
contract L1SharedBridgeTest is L1SharedBridge {
// add this to be excluded from coverage report
function test() internal virtual {}

address private immutable eraDiamondProxy;

constructor(
address _diamondProxyAddress,
address payable _l1WethAddress,
IBridgehub _bridgehub,
IL1ERC20Bridge _legacyBridge
) L1SharedBridge(_l1WethAddress, _bridgehub, _legacyBridge) {
eraDiamondProxy = _diamondProxyAddress;
}
IL1ERC20Bridge _legacyBridge,
uint256 _eraChainId,
address _eraErc20BridgeAddress
)
L1SharedBridge(
_l1WethAddress,
_bridgehub,
_legacyBridge,
_eraChainId,
_eraErc20BridgeAddress,
_diamondProxyAddress
)
{}

/// @notice Checks that the message sender is the bridgehub or Era
modifier onlyBridgehubOrTestEra(uint256 _chainId) {
require(
(msg.sender == address(bridgehub)) || (_chainId == ERA_CHAIN_ID && msg.sender == eraDiamondProxy),
(msg.sender == address(bridgehub)) || (_chainId == eraChainId && msg.sender == eraDiamondProxy),
"L1SharedBridge: not bridgehub or era chain"
);
_;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ contract MailboxFacetTest is MailboxFacet {
// add this to be excluded from coverage report
function test() internal virtual {}

constructor() {
constructor(uint256 _eraChainId) MailboxFacet(_eraChainId) {
s.admin = msg.sender;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {L2CanonicalTransaction} from "../common/Messaging.sol";
import {Ownable2Step} from "@openzeppelin/contracts/access/Ownable2Step.sol";
import {ProposedUpgrade} from "../upgrades/BaseZkSyncUpgrade.sol";
import {ReentrancyGuard} from "../common/ReentrancyGuard.sol";
import {REQUIRED_L2_GAS_PRICE_PER_PUBDATA, L2_TO_L1_LOG_SERIALIZE_SIZE, DEFAULT_L2_LOGS_TREE_ROOT_HASH, EMPTY_STRING_KECCAK, SYSTEM_UPGRADE_L2_TX_TYPE} from "../common/Config.sol";
import {REQUIRED_L2_GAS_PRICE_PER_PUBDATA, L2_TO_L1_LOG_SERIALIZE_SIZE, DEFAULT_L2_LOGS_TREE_ROOT_HASH, EMPTY_STRING_KECCAK, SYSTEM_UPGRADE_L2_TX_TYPE, PRIORITY_TX_MAX_GAS_LIMIT} from "../common/Config.sol";
import {VerifierParams} from "./chain-interfaces/IVerifier.sol";

/// @title StateTransition contract
Expand Down Expand Up @@ -184,7 +184,7 @@ contract StateTransitionManager is IStateTransitionManager, ReentrancyGuard, Own
txType: SYSTEM_UPGRADE_L2_TX_TYPE,
from: uint256(uint160(L2_FORCE_DEPLOYER_ADDR)),
to: uint256(uint160(L2_SYSTEM_CONTEXT_SYSTEM_CONTRACT_ADDR)),
gasLimit: $(PRIORITY_TX_MAX_GAS_LIMIT),
gasLimit: PRIORITY_TX_MAX_GAS_LIMIT,
gasPerPubdataByteLimit: REQUIRED_L2_GAS_PRICE_PER_PUBDATA,
maxFeePerGas: uint256(0),
maxPriorityFeePerGas: uint256(0),
Expand Down
34 changes: 34 additions & 0 deletions l1-contracts/contracts/state-transition/TestnetVerifier.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// SPDX-License-Identifier: MIT

pragma solidity 0.8.20;

import {Verifier} from "./Verifier.sol";
import {IVerifier} from "./chain-interfaces/IVerifier.sol";

/// @author Matter Labs
/// @custom:security-contact [email protected]
/// @notice Modified version of the main verifier contract for the testnet environment
/// @dev This contract is used to skip the zkp verification for the testnet environment.
/// If the proof is not empty, it will verify it using the main verifier contract,
/// otherwise, it will skip the verification.
contract TestnetVerifier is Verifier {
constructor() {
assert(block.chainid != 1);
}

/// @dev Verifies a zk-SNARK proof, skipping the verification if the proof is empty.
/// @inheritdoc IVerifier
function verify(
uint256[] calldata _publicInputs,
uint256[] calldata _proof,
uint256[] calldata _recursiveAggregationInput
) public view override returns (bool) {
// We allow skipping the zkp verification for the test(net) environment
// If the proof is not empty, verify it, otherwise, skip the verification
if (_proof.length == 0) {
return true;
}

return super.verify(_publicInputs, _proof, _recursiveAggregationInput);
}
}
Loading

0 comments on commit c5fca0c

Please sign in to comment.