Skip to content

Commit

Permalink
Merge pull request #14 from matter-labs/sb-rename-ergs-gas
Browse files Browse the repository at this point in the history
Rename ergs->gas
  • Loading branch information
StanislavBreadless authored Feb 1, 2023
2 parents e640939 + 2511319 commit be2c481
Show file tree
Hide file tree
Showing 45 changed files with 568 additions and 434 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@ See the [documentation](https://v2-docs.zksync.io/dev/fundamentals/rollups.html)
- **Validator/Operator** - a privileged address that can commit/verify/execute L2 blocks.
- **Facet** - implementation contract. The word comes from the EIP-2535.
- **Security council** - set of trusted addresses that can decrease upgrade timelock.
- **Ergs** - a unit that measures the amount of computational effort required to execute specific operations on the
zkSync v2 network. Analog of the gas on Ethereum.
- **Gas** - a unit that measures the amount of computational effort required to execute specific operations on the
zkSync v2 network. In order to distinguish it from Ethereum's gas, we will often refer to zkSync's gas as L2 gas and
to the Ethereum's gas as L1 gas. If no prefix is used, "gas" reffers to L2 gas.

### L1 Smart contracts

Expand Down
34 changes: 17 additions & 17 deletions SystemConfig.json
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
{
"L2_TX_MAX_ERGS_LIMIT": 80000000,
"MAX_PUBDATA_PER_BLOCK": 110000,
"PRIORITY_TX_MAX_PUBDATA": 99000,
"FAIR_ERGS_PRICE_PER_PUBDATA": 500000000,
"GAS_PER_PUBDATA_BYTE": 17,
"BLOCK_OVERHEAD_ERGS": 1200000,
"BLOCK_OVERHEAD_L1_GAS": 1000000,
"MAX_TRANSACTIONS_IN_BLOCK": 256,
"BOOTLOADER_TX_ENCODING_SPACE": 522857,
"L1_TX_INTRINSIC_ERGS": 159849,
"L1_TX_INTRINSIC_PUBDATA": 88,
"L1_TX_MIN_ERGS_BASE": 166479,
"L1_TX_DELTA_544_ENCODING_BYTES": 1656,
"L1_TX_DELTA_FACTORY_DEPS_ERGS": 2631,
"L1_TX_DELTA_FACTORY_DEPS_PUBDATA": 64,
"MAX_NEW_FACTORY_DEPS": 32,
"DEFAULT_ERGS_PRICE_PER_PUBDATA": 800
"L2_TX_MAX_GAS_LIMIT": 80000000,
"MAX_PUBDATA_PER_BLOCK": 110000,
"PRIORITY_TX_MAX_PUBDATA": 99000,
"FAIR_L2_GAS_PRICE": 500000000,
"L1_GAS_PER_PUBDATA_BYTE": 17,
"BLOCK_OVERHEAD_L2_GAS": 1200000,
"BLOCK_OVERHEAD_L1_GAS": 1000000,
"MAX_TRANSACTIONS_IN_BLOCK": 256,
"BOOTLOADER_TX_ENCODING_SPACE": 522857,
"L1_TX_INTRINSIC_L2_GAS": 166400,
"L1_TX_INTRINSIC_PUBDATA": 88,
"L1_TX_MIN_L2_GAS_BASE": 172726,
"L1_TX_DELTA_544_ENCODING_BYTES": 1656,
"L1_TX_DELTA_FACTORY_DEPS_L2_GAS": 2473,
"L1_TX_DELTA_FACTORY_DEPS_PUBDATA": 64,
"MAX_NEW_FACTORY_DEPS": 32,
"DEFAULT_L2_GAS_PRICE_PER_PUBDATA": 800
}
2 changes: 1 addition & 1 deletion ethereum/.env
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
CHAIN_ETH_NETWORK=localhost
CONTRACTS_PRIORITY_TX_MAX_ERGS_LIMIT=72000000
CONTRACTS_PRIORITY_TX_MAX_GAS_LIMIT=72000000
ETH_CLIENT_WEB3_URL=http://127.0.0.1:8545
100 changes: 69 additions & 31 deletions ethereum/contracts/bridge/L1ERC20Bridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import "../common/AllowListed.sol";
import "../common/libraries/UnsafeBytes.sol";
import "../common/ReentrancyGuard.sol";
import "../common/L2ContractHelper.sol";
import "../vendor/AddressAliasHelper.sol";

/// @author Matter Labs
/// @notice Smart contract that allows depositing ERC20 tokens from Ethereum to zkSync v2.0
Expand All @@ -28,12 +29,12 @@ contract L1ERC20Bridge is IL1Bridge, AllowListed, ReentrancyGuard {
/// @dev zkSync smart contract that used to operate with L2 via asynchronous L2 <-> L1 communication
IMailbox immutable zkSyncMailbox;

/// @dev Ergs limit for requesting L1 -> L2 transaction of deploying L2 bridge instance
/// NOTE: constant is not calculated accurately, because ergs count in L2 is not stable yet
uint256 constant DEPLOY_L2_BRIDGE_COUNTERPART_ERGS_LIMIT = $(PRIORITY_TX_MAX_ERGS_LIMIT);
/// @dev The L2 gas limit for requesting L1 -> L2 transaction of deploying L2 bridge instance
/// NOTE: this constant will be accurately calculated in the future.
uint256 constant DEPLOY_L2_BRIDGE_COUNTERPART_GAS_LIMIT = $(PRIORITY_TX_MAX_GAS_LIMIT);

/// @dev The default ergsPricePerPubdata to be used in bridges.
uint256 constant DEFAULT_ERGS_PRICE_PER_PUBDATA = $(DEFAULT_ERGS_PRICE_PER_PUBDATA);
/// @dev The default l2GasPricePerPubdata to be used in bridges.
uint256 constant DEFAULT_L2_GAS_PRICE_PER_PUBDATA = $(DEFAULT_L2_GAS_PRICE_PER_PUBDATA);

/// @dev A mapping L2 block number => message number => flag
/// @dev Used to indicate that zkSync L2 -> L1 message was already processed
Expand Down Expand Up @@ -62,64 +63,101 @@ contract L1ERC20Bridge is IL1Bridge, AllowListed, ReentrancyGuard {
/// @dev Initializes a contract bridge for later use. Expected to be used in the proxy
/// @dev During initialization deploys L2 bridge counterpart as well as provides some factory deps for it
/// @param _factoryDeps A list of raw bytecodes that are needed for deployment of the L2 bridge
/// @notice _factoryDeps[0] == a raw bytecode of L2 bridge
/// @notice _factoryDeps[1] == a raw bytecode of token proxy
/// @notice _factoryDeps[0] == a raw bytecode of L2 bridge implementation
/// @notice _factoryDeps[1] == a raw bytecode of proxy that is used as L2 bridge
/// @notice _factoryDeps[2] == a raw bytecode of token proxy
/// @param _l2TokenFactory Pre-calculated address of L2 token beacon proxy
/// @notice At the time of the function call, it is not yet deployed in L2, but knowledge of its address
/// @notice is necessary for determining L2 token address by L1 address, see `l2TokenAddress(address)` function
/// @param _governor Address which can change L2 token implementation
/// @param _governor Address which can change L2 token implementation and upgrade the bridge
function initialize(
bytes[] calldata _factoryDeps,
address _l2TokenFactory,
address _governor
) external reentrancyGuardInitializer {
require(_l2TokenFactory != address(0), "nf");
require(_governor != address(0), "nh");
// We are expecting to see the exact two bytecodes that are needed to initialize the bridge
require(_factoryDeps.length == 2, "mk");
l2ProxyTokenBytecodeHash = L2ContractHelper.hashL2Bytecode(_factoryDeps[1]);
// We are expecting to see the exact three bytecodes that are needed to initialize the bridge
require(_factoryDeps.length == 3, "mk");
l2ProxyTokenBytecodeHash = L2ContractHelper.hashL2Bytecode(_factoryDeps[2]);
l2TokenFactory = _l2TokenFactory;

bytes32 create2Salt = bytes32(0);
bytes memory create2Input = abi.encode(address(this), l2ProxyTokenBytecodeHash, _governor);
bytes32 l2BridgeBytecodeHash = L2ContractHelper.hashL2Bytecode(_factoryDeps[0]);
bytes memory deployL2BridgeCalldata = abi.encodeCall(
IContractDeployer.create2,
(create2Salt, l2BridgeBytecodeHash, create2Input)
bytes32 l2BridgeImplementationBytecodeHash = L2ContractHelper.hashL2Bytecode(_factoryDeps[0]);
bytes32 l2BridgeProxyBytecodeHash = L2ContractHelper.hashL2Bytecode(_factoryDeps[1]);

// Deploy L2 bridge implementation contract
address bridgeImplementationAddr = _requestDeployTransaction(
l2BridgeImplementationBytecodeHash,
"", // Empty constructor data
_factoryDeps // All factory deps are needed for L2 bridge
);

l2Bridge = L2ContractHelper.computeCreate2Address(
address(this),
create2Salt,
l2BridgeBytecodeHash,
keccak256(create2Input)
// Prepare the proxy constructor data
bytes memory l2BridgeProxyConstructorData;
{
// Data to be used in delegate call to initialize the proxy
bytes memory proxyInitializationParams = abi.encodeCall(
IL2Bridge.initialize,
(address(this), l2ProxyTokenBytecodeHash, _governor)
);
l2BridgeProxyConstructorData = abi.encode(bridgeImplementationAddr, _governor, proxyInitializationParams);
}

// Deploy L2 bridge proxy contract
l2Bridge = _requestDeployTransaction(
l2BridgeProxyBytecodeHash,
l2BridgeProxyConstructorData,
new bytes[](0) // No factory deps are needed for L2 bridge proxy, because it is already passed in previous step
);
}

/// @notice Requests L2 transaction that will deploy a contract with a given bytecode hash and constructor data.
/// NOTE: it is always use deploy via create2 with ZERO salt
/// @param _bytecodeHash The hash of the bytecode of the contract to be deployed
/// @param _constructorData The data to be passed to the contract constructor
/// @param _factoryDeps A list of raw bytecodes that are needed for deployment
function _requestDeployTransaction(
bytes32 _bytecodeHash,
bytes memory _constructorData,
bytes[] memory _factoryDeps
) internal returns (address deployedAddress) {
bytes memory deployCalldata = abi.encodeCall(
IContractDeployer.create2,
(bytes32(0), _bytecodeHash, _constructorData)
);
zkSyncMailbox.requestL2Transaction(
DEPLOYER_SYSTEM_CONTRACT_ADDRESS,
0,
deployL2BridgeCalldata,
DEPLOY_L2_BRIDGE_COUNTERPART_ERGS_LIMIT,
DEFAULT_ERGS_PRICE_PER_PUBDATA,
deployCalldata,
DEPLOY_L2_BRIDGE_COUNTERPART_GAS_LIMIT,
DEFAULT_L2_GAS_PRICE_PER_PUBDATA,
_factoryDeps,
msg.sender
);

deployedAddress = L2ContractHelper.computeCreate2Address(
// Apply the alias to the address of the bridge contract, to get the `msg.sender` in L2.
AddressAliasHelper.applyL1ToL2Alias(address(this)),
bytes32(0), // Zero salt
_bytecodeHash,
keccak256(_constructorData)
);
}

/// @notice Initiates a deposit by locking funds on the contract and sending the request
/// of processing an L2 transaction where tokens would be minted
/// @param _l2Receiver The account address that should receive funds on L2
/// @param _l1Token The L1 token address which is deposited
/// @param _amount The total amount of tokens to be bridged
/// @param _l2TxErgsLimit The ergs limit to be used in the corresponding L2 transaction
/// @param _l2TxErgsPerPubdataByte The ergsPerPubdataByteLimit to be used in the corresponding L2 transaction
/// @param _l2TxGasLimit The L2 gas limit to be used in the corresponding L2 transaction
/// @param _l2TxGasPerPubdataByte The gasPerPubdataByteLimit to be used in the corresponding L2 transaction
/// @return txHash The L2 transaction hash of deposit finalization
function deposit(
address _l2Receiver,
address _l1Token,
uint256 _amount,
uint256 _l2TxErgsLimit,
uint256 _l2TxErgsPerPubdataByte
uint256 _l2TxGasLimit,
uint256 _l2TxGasPerPubdataByte
) external payable nonReentrant senderCanCallFunction(allowList) returns (bytes32 txHash) {
require(_amount != 0, "2T"); // empty deposit amount
uint256 amount = _depositFunds(msg.sender, IERC20(_l1Token), _amount);
Expand All @@ -130,8 +168,8 @@ contract L1ERC20Bridge is IL1Bridge, AllowListed, ReentrancyGuard {
l2Bridge,
0, // L2 msg.value
l2TxCalldata,
_l2TxErgsLimit,
_l2TxErgsPerPubdataByte,
_l2TxGasLimit,
_l2TxGasPerPubdataByte,
new bytes[](0),
msg.sender
);
Expand Down
4 changes: 2 additions & 2 deletions ethereum/contracts/bridge/interfaces/IL1Bridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ interface IL1Bridge {
address _l2Receiver,
address _l1Token,
uint256 _amount,
uint256 _l2TxErgsLimit,
uint256 _l2TxErgsPerPubdataByte
uint256 _l2TxGasLimit,
uint256 _l2TxGasPerPubdataByte
) external payable returns (bytes32 txHash);

function claimFailedDeposit(
Expand Down
6 changes: 6 additions & 0 deletions ethereum/contracts/bridge/interfaces/IL2Bridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ pragma solidity ^0.8.0;

/// @author Matter Labs
interface IL2Bridge {
function initialize(
address _l1Bridge,
bytes32 _l2TokenProxyBytecodeHash,
address _governor
) external;

function finalizeDeposit(
address _l1Sender,
address _l2Receiver,
Expand Down
43 changes: 43 additions & 0 deletions ethereum/contracts/vendor/AddressAliasHelper.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// SPDX-License-Identifier: Apache-2.0

/*
* Copyright 2019-2021, Offchain Labs, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

pragma solidity ^0.8.0;

library AddressAliasHelper {
uint160 constant offset = uint160(0x1111000000000000000000000000000000001111);

/// @notice Utility function that converts the address in the L1 that submitted a tx to
/// the inbox to the msg.sender viewed in the L2
/// @param l1Address the address in the L1 that triggered the tx to L2
/// @return l2Address L2 address as viewed in msg.sender
function applyL1ToL2Alias(address l1Address) internal pure returns (address l2Address) {
unchecked {
l2Address = address(uint160(l1Address) + offset);
}
}

/// @notice Utility function that converts the msg.sender viewed in the L2 to the
/// address in the L1 that submitted a tx to the inbox
/// @param l2Address L2 address as viewed in msg.sender
/// @return l1Address the address in the L1 that triggered the tx to L2
function undoL1ToL2Alias(address l2Address) internal pure returns (address l1Address) {
unchecked {
l1Address = address(uint160(l2Address) - offset);
}
}
}
34 changes: 17 additions & 17 deletions ethereum/contracts/zksync/Config.sol
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,8 @@ uint256 constant COMMIT_TIMESTAMP_APPROXIMATION_DELTA = $$(
/// @dev Bit mask to apply for verifier public input before verifying.
uint256 constant INPUT_MASK = $$(~uint256(0) >> 8);

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

/// @dev The maximum number of the pubdata an L2 operation should be allowed to use.
uint256 constant MAX_PUBDATA_PER_BLOCK = $(MAX_PUBDATA_PER_BLOCK);
Expand All @@ -88,48 +88,48 @@ uint256 constant MAX_PUBDATA_PER_BLOCK = $(MAX_PUBDATA_PER_BLOCK);
/// to ensure that the transaction is definitely processable on L2 despite any potential overhead.
uint256 constant PRIORITY_TX_MAX_PUBDATA = $(PRIORITY_TX_MAX_PUBDATA);

/// @dev The default price per erg to be used for L1->L2 transactions
uint256 constant FAIR_ERGS_PRICE_PER_PUBDATA = $(FAIR_ERGS_PRICE_PER_PUBDATA);
/// @dev The default price per L2 gas to be used for L1->L2 transactions
uint256 constant FAIR_L2_GAS_PRICE = $(FAIR_L2_GAS_PRICE);

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

/// @dev The computational overhead of processing an L2 block.
uint256 constant BLOCK_OVERHEAD_ERGS = $(BLOCK_OVERHEAD_ERGS);
uint256 constant BLOCK_OVERHEAD_L2_GAS = $(BLOCK_OVERHEAD_L2_GAS);

/// @dev The overhead in L1 gas of interacting with the L1
uint256 constant BLOCK_OVERHEAD_L1_GAS = $(BLOCK_OVERHEAD_L1_GAS);

/// @dev The equivalent in L1 pubdata of L1 gas used for working with L1
uint256 constant BLOCK_OVERHEAD_PUBDATA = BLOCK_OVERHEAD_L1_GAS / GAS_PER_PUBDATA_BYTE;
uint256 constant BLOCK_OVERHEAD_PUBDATA = BLOCK_OVERHEAD_L1_GAS / L1_GAS_PER_PUBDATA_BYTE;

/// @dev The maximum number of transactions in L2 block:
uint256 constant MAX_TRANSACTIONS_IN_BLOCK = $(MAX_TRANSACTIONS_IN_BLOCK);

/// @dev The size of the bootloader memory dedicated to the encodings of transactions
uint256 constant BOOTLOADER_TX_ENCODING_SPACE = $(BOOTLOADER_TX_ENCODING_SPACE);

/// @dev The intrinsic cost of the L1->l2 transaction in computational ergs
uint256 constant L1_TX_INTRINSIC_ERGS = $(L1_TX_INTRINSIC_ERGS);
/// @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);

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

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

/// @dev The number of ergs the transaction starts costing more with each 544 bytes of encoding
/// @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);

/// @dev The number of ergs an L1->L2 transaction gains with each new factory dependency
uint256 constant L1_TX_DELTA_FACTORY_DEPS_ERGS = $(L1_TX_DELTA_FACTORY_DEPS_ERGS);
/// @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);

/// @dev The number of ergs an L1->L2 transaction gains with each new factory dependency
/// @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);

/// @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);

/// @dev The default ergsPricePerPubdata to be used in bridges.
uint256 constant DEFAULT_ERGS_PRICE_PER_PUBDATA = $(DEFAULT_ERGS_PRICE_PER_PUBDATA);
/// @dev The default L2 gasPricePerPubdata to be used in bridges.
uint256 constant DEFAULT_L2_GAS_PRICE_PER_PUBDATA = $(DEFAULT_L2_GAS_PRICE_PER_PUBDATA);
6 changes: 3 additions & 3 deletions ethereum/contracts/zksync/DiamondInit.sol
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ contract DiamondInit is Base {
/// @param _zkPorterIsAvailable The availability of zk porter shard
/// @param _l2BootloaderBytecodeHash The hash of bootloader L2 bytecode
/// @param _l2DefaultAccountBytecodeHash The hash of default account L2 bytecode
/// @param _priorityTxMaxErgsLimit The maximum number of ergs that a user can request for L1 -> L2 transactions
/// @param _priorityTxMaxGasLimit maximum number of the L2 gas that a user can request for L1 -> L2 transactions
/// @return Magic 32 bytes, which indicates that the contract logic is expected to be used as a diamond proxy initializer
function initialize(
Verifier _verifier,
Expand All @@ -41,7 +41,7 @@ contract DiamondInit is Base {
bool _zkPorterIsAvailable,
bytes32 _l2BootloaderBytecodeHash,
bytes32 _l2DefaultAccountBytecodeHash,
uint256 _priorityTxMaxErgsLimit
uint256 _priorityTxMaxGasLimit
) external reentrancyGuardInitializer returns (bytes32) {
require(address(_verifier) != address(0), "vt");
require(_governor != address(0), "vy");
Expand All @@ -68,7 +68,7 @@ contract DiamondInit is Base {
s.zkPorterIsAvailable = _zkPorterIsAvailable;
s.l2BootloaderBytecodeHash = _l2BootloaderBytecodeHash;
s.l2DefaultAccountBytecodeHash = _l2DefaultAccountBytecodeHash;
s.priorityTxMaxErgsLimit = _priorityTxMaxErgsLimit;
s.priorityTxMaxGasLimit = _priorityTxMaxGasLimit;

return Diamond.DIAMOND_INIT_SUCCESS_RETURN_VALUE;
}
Expand Down
Loading

0 comments on commit be2c481

Please sign in to comment.