Skip to content

Commit

Permalink
Merge branch 'main' of github.com:lambdaclass/era-contracts into vali…
Browse files Browse the repository at this point in the history
…dium_mode
  • Loading branch information
Ivan Litteri authored and Ivan Litteri committed Jan 23, 2024
2 parents 6f40ca2 + 583cb67 commit 92fa800
Show file tree
Hide file tree
Showing 139 changed files with 4,373 additions and 4,155 deletions.
5 changes: 4 additions & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,8 @@
"import/namespace": "off",
"import/no-unresolved": "off",
"import/order": "off"
}
},
"ignorePatterns": [
"**/lib/*"
]
}
49 changes: 49 additions & 0 deletions .github/workflows/buld-release.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: Build and release

on:
push:
branches:
- "*"

jobs:
build-contracts:
runs-on: ubuntu-latest

steps:
- name: Checkout the repository
uses: actions/checkout@v3

- name: Use Node.js
uses: actions/setup-node@v3
with:
node-version: 18.18.0
cache: yarn

- name: Init
id: init
run: |
yarn
echo "release_tag=$(echo ${GITHUB_REF#refs/heads/})-$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
- name: Build contracts
run: |
yarn l1 build
yarn l2 build
yarn sc build
- name: Prepare artifacts
run: |
tar -czvf l1-contracts.tar.gz ./l1-contracts
tar -czvf l2-contracts.tar.gz ./l2-contracts
tar -czvf system-contracts.tar.gz ./system-contracts
- name: Release
uses: softprops/action-gh-release@v1
with:
tag_name: ${{ steps.init.outputs.release_tag }}
fail_on_unmatched_files: true
body: ""
files: |
l1-contracts.tar.gz
l2-contracts.tar.gz
system-contracts.tar.gz
4 changes: 0 additions & 4 deletions .github/workflows/l1-contracts-ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,6 @@ name: L1 contracts CI

on:
pull_request:
push:
branches:
- dev
- main

jobs:
build:
Expand Down
4 changes: 0 additions & 4 deletions .github/workflows/l2-contracts-ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,6 @@ name: L2 contracts CI

on:
pull_request:
push:
branches:
- dev
- main

jobs:
build:
Expand Down
16 changes: 4 additions & 12 deletions .github/workflows/system-contracts-ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,6 @@ name: System contracts CI

on:
pull_request:
push:
branches:
- dev
- main

jobs:
build:
Expand Down Expand Up @@ -35,8 +31,7 @@ jobs:
system-contracts/artifacts-zk
system-contracts/cache-zk
system-contracts/typechain
system-contracts/contracts/artifacts
system-contracts/contracts/precompiles/artifacts
system-contracts/contracts-preprocessed
system-contracts/bootloader/build
lint:
Expand Down Expand Up @@ -80,8 +75,7 @@ jobs:
system-contracts/artifacts-zk
system-contracts/cache-zk
system-contracts/typechain
system-contracts/contracts/artifacts
system-contracts/contracts/precompiles/artifacts
system-contracts/contracts-preprocessed
system-contracts/bootloader/build
- name: Run bootloader tests
Expand Down Expand Up @@ -120,8 +114,7 @@ jobs:
system-contracts/artifacts-zk
system-contracts/cache-zk
system-contracts/typechain
system-contracts/contracts/artifacts
system-contracts/contracts/precompiles/artifacts
system-contracts/contracts-preprocessed
system-contracts/bootloader/build
- name: Run tests
Expand Down Expand Up @@ -157,8 +150,7 @@ jobs:
system-contracts/artifacts-zk
system-contracts/cache-zk
system-contracts/typechain
system-contracts/contracts/artifacts
system-contracts/contracts/precompiles/artifacts
system-contracts/contracts-preprocessed
system-contracts/bootloader/build
- name: Check hashes
Expand Down
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.DS_Store
.idea
.vscode
artifacts-forge/
Expand All @@ -7,7 +8,8 @@ build/
cache-forge/
cache-zk/
cache/
.DS_Store
contracts-preprocessed/
era_test_node.log*
node_modules/
target/
tools/data/Verifier.sol
Expand Down
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
[submodule "l1-contracts/lib/forge-std"]
path = l1-contracts/lib/forge-std
url = https://github.com/foundry-rs/forge-std
[submodule "l1-contracts/lib/murky"]
path = l1-contracts/lib/murky
url = https://github.com/dmfxyz/murky
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
tools/data
l1-contracts/lib
system-contracts/contracts/openzeppelin
system-contracts/contracts/Constants.sol
1 change: 1 addition & 0 deletions .solhintignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ l2-contracts/node_modules

# system-contracts
system-contracts/contracts/openzeppelin
system-contracts/contracts/Constants.sol
27 changes: 0 additions & 27 deletions docs/Overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -258,11 +258,6 @@ validator can prove the already commited batches regardless of the mentioned tim
to the `proveBatches` function) will be propogated to the zkSync contract. After, the `delay` is elapsed, the validator
is allowed to call `executeBatches` to propogate the same calldata to zkSync contract.

#### Allowlist

The auxiliary contract controls the permission access list. It is used in bridges and diamond proxies to control which
addresses can interact with them in the Alpha release.

### L2 specifics

#### Deployment
Expand Down Expand Up @@ -293,25 +288,3 @@ Thus:
- L2 contracts are deployed by bytecode hash, not by full bytecode
- Factory dependencies - list of bytecode hashes that can be deployed on L2
- Address derivation for `create`/`create2` on L1 and L2 is different

### Deposit Limitation

The amount of deposit can be limited. This limitation is applied on an account level and is not time-based. In other
words, each account cannot deposit more than the cap defined. The tokens and the cap can be set through governance
transactions. Moreover, there is an allow listing mechanism as well (only some allow listed accounts can call some
specific functions). So, the combination of deposit limitation and allow listing leads to limiting the deposit of the
allow listed account to be less than the defined cap.

```solidity
struct Deposit {
bool depositLimitation;
uint256 depositCap;
}
```

Currently, the limit is used only for blocking deposits of the specific token (turning on the limitation and setting the
limit to zero). And on the near future, this functionality will be completely removed.

See the
[documentation](https://era.zksync.io/docs/dev/building-on-zksync/contracts/contract-development.html#solidity-vyper-support)
to read more!
37 changes: 6 additions & 31 deletions l1-contracts/contracts/bridge/L1ERC20Bridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ import "./interfaces/IL2ERC20Bridge.sol";
import "./libraries/BridgeInitializationHelper.sol";

Check warning on line 13 in l1-contracts/contracts/bridge/L1ERC20Bridge.sol

View workflow job for this annotation

GitHub Actions / lint

global import of path ./libraries/BridgeInitializationHelper.sol is not allowed. Specify names to import individually or bind all exports of the module into a name (import "path" as Name)

Check warning on line 13 in l1-contracts/contracts/bridge/L1ERC20Bridge.sol

View workflow job for this annotation

GitHub Actions / lint

global import of path ./libraries/BridgeInitializationHelper.sol is not allowed. Specify names to import individually or bind all exports of the module into a name (import "path" as Name)

Check warning on line 13 in l1-contracts/contracts/bridge/L1ERC20Bridge.sol

View workflow job for this annotation

GitHub Actions / lint

global import of path ./libraries/BridgeInitializationHelper.sol is not allowed. Specify names to import individually or bind all exports of the module into a name (import "path" as Name)

import "../zksync/interfaces/IZkSync.sol";

Check warning on line 15 in l1-contracts/contracts/bridge/L1ERC20Bridge.sol

View workflow job for this annotation

GitHub Actions / lint

global import of path ../zksync/interfaces/IZkSync.sol is not allowed. Specify names to import individually or bind all exports of the module into a name (import "path" as Name)

Check warning on line 15 in l1-contracts/contracts/bridge/L1ERC20Bridge.sol

View workflow job for this annotation

GitHub Actions / lint

global import of path ../zksync/interfaces/IZkSync.sol is not allowed. Specify names to import individually or bind all exports of the module into a name (import "path" as Name)

Check warning on line 15 in l1-contracts/contracts/bridge/L1ERC20Bridge.sol

View workflow job for this annotation

GitHub Actions / lint

global import of path ../zksync/interfaces/IZkSync.sol is not allowed. Specify names to import individually or bind all exports of the module into a name (import "path" as Name)
import "../common/interfaces/IAllowList.sol";
import "../common/AllowListed.sol";
import "../common/libraries/UnsafeBytes.sol";

Check warning on line 16 in l1-contracts/contracts/bridge/L1ERC20Bridge.sol

View workflow job for this annotation

GitHub Actions / lint

global import of path ../common/libraries/UnsafeBytes.sol is not allowed. Specify names to import individually or bind all exports of the module into a name (import "path" as Name)

Check warning on line 16 in l1-contracts/contracts/bridge/L1ERC20Bridge.sol

View workflow job for this annotation

GitHub Actions / lint

global import of path ../common/libraries/UnsafeBytes.sol is not allowed. Specify names to import individually or bind all exports of the module into a name (import "path" as Name)

Check warning on line 16 in l1-contracts/contracts/bridge/L1ERC20Bridge.sol

View workflow job for this annotation

GitHub Actions / lint

global import of path ../common/libraries/UnsafeBytes.sol is not allowed. Specify names to import individually or bind all exports of the module into a name (import "path" as Name)
import "../common/libraries/L2ContractHelper.sol";

Check warning on line 17 in l1-contracts/contracts/bridge/L1ERC20Bridge.sol

View workflow job for this annotation

GitHub Actions / lint

global import of path ../common/libraries/L2ContractHelper.sol is not allowed. Specify names to import individually or bind all exports of the module into a name (import "path" as Name)

Check warning on line 17 in l1-contracts/contracts/bridge/L1ERC20Bridge.sol

View workflow job for this annotation

GitHub Actions / lint

global import of path ../common/libraries/L2ContractHelper.sol is not allowed. Specify names to import individually or bind all exports of the module into a name (import "path" as Name)

Check warning on line 17 in l1-contracts/contracts/bridge/L1ERC20Bridge.sol

View workflow job for this annotation

GitHub Actions / lint

global import of path ../common/libraries/L2ContractHelper.sol is not allowed. Specify names to import individually or bind all exports of the module into a name (import "path" as Name)
import "../common/ReentrancyGuard.sol";
Expand All @@ -25,12 +23,9 @@ import "../vendor/AddressAliasHelper.sol";
/// @notice Smart contract that allows depositing ERC20 tokens from Ethereum to zkSync Era
/// @dev It is standard implementation of ERC20 Bridge that can be used as a reference
/// for any other custom token bridges.
contract L1ERC20Bridge is IL1Bridge, IL1BridgeLegacy, AllowListed, ReentrancyGuard {
contract L1ERC20Bridge is IL1Bridge, IL1BridgeLegacy, ReentrancyGuard {
using SafeERC20 for IERC20;

/// @dev The smart contract that manages the list with permission to call contract functions
IAllowList internal immutable allowList;

/// @dev zkSync smart contract that is used to operate with L2 via asynchronous L2 <-> L1 communication
IZkSync internal immutable zkSync;

Expand Down Expand Up @@ -62,9 +57,8 @@ contract L1ERC20Bridge is IL1Bridge, IL1BridgeLegacy, AllowListed, ReentrancyGua

/// @dev Contract is expected to be used as proxy implementation.
/// @dev Initialize the implementation to prevent Parity hack.
constructor(IZkSync _zkSync, IAllowList _allowList) reentrancyGuardInitializer {
constructor(IZkSync _zkSync) reentrancyGuardInitializer {
zkSync = _zkSync;
allowList = _allowList;
}

/// @dev Initializes a contract bridge for later use. Expected to be used in the proxy
Expand Down Expand Up @@ -139,8 +133,7 @@ contract L1ERC20Bridge is IL1Bridge, IL1BridgeLegacy, AllowListed, ReentrancyGua
/// @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 l2TxHash The L2 transaction hash of deposit finalization
/// NOTE: the function doesn't use `nonreentrant` and `senderCanCallFunction` modifiers, because the inner
/// method does.
/// NOTE: the function doesn't use `nonreentrant` modifier, because the inner method does.
function deposit(
address _l2Receiver,
address _l1Token,
Expand Down Expand Up @@ -180,12 +173,10 @@ contract L1ERC20Bridge is IL1Bridge, IL1BridgeLegacy, AllowListed, ReentrancyGua
uint256 _l2TxGasLimit,
uint256 _l2TxGasPerPubdataByte,
address _refundRecipient
) public payable nonReentrant senderCanCallFunction(allowList) returns (bytes32 l2TxHash) {
) public payable nonReentrant returns (bytes32 l2TxHash) {
require(_amount != 0, "2T"); // empty deposit amount
uint256 amount = _depositFunds(msg.sender, IERC20(_l1Token), _amount);
require(amount == _amount, "1T"); // The token has non-standard transfer logic
// verify the deposit amount is allowed
_verifyDepositLimit(_l1Token, msg.sender, _amount, false);

bytes memory l2TxCalldata = _getDepositL2Calldata(msg.sender, _l2Receiver, _l1Token, amount);
// If the refund recipient is not specified, the refund will be sent to the sender of the transaction.
Expand Down Expand Up @@ -260,7 +251,7 @@ contract L1ERC20Bridge is IL1Bridge, IL1BridgeLegacy, AllowListed, ReentrancyGua
uint256 _l2MessageIndex,
uint16 _l2TxNumberInBatch,
bytes32[] calldata _merkleProof
) external nonReentrant senderCanCallFunction(allowList) {
) external nonReentrant {
bool proofValid = zkSync.proveL1ToL2TransactionStatus(
_l2TxHash,
_l2BatchNumber,
Expand All @@ -274,9 +265,6 @@ contract L1ERC20Bridge is IL1Bridge, IL1BridgeLegacy, AllowListed, ReentrancyGua
uint256 amount = depositAmount[_depositSender][_l1Token][_l2TxHash];
require(amount > 0, "y1");

// Change the total deposited amount by the user
_verifyDepositLimit(_l1Token, _depositSender, amount, true);

delete depositAmount[_depositSender][_l1Token][_l2TxHash];
// Withdraw funds
IERC20(_l1Token).safeTransfer(_depositSender, amount);
Expand All @@ -296,7 +284,7 @@ contract L1ERC20Bridge is IL1Bridge, IL1BridgeLegacy, AllowListed, ReentrancyGua
uint16 _l2TxNumberInBatch,
bytes calldata _message,
bytes32[] calldata _merkleProof
) external nonReentrant senderCanCallFunction(allowList) {
) external nonReentrant {
require(!isWithdrawalFinalized[_l2BatchNumber][_l2MessageIndex], "pw");

L2Message memory l2ToL1Message = L2Message({
Expand Down Expand Up @@ -336,19 +324,6 @@ contract L1ERC20Bridge is IL1Bridge, IL1BridgeLegacy, AllowListed, ReentrancyGua
(amount, offset) = UnsafeBytes.readUint256(_l2ToL1message, offset);
}

/// @dev Verify the deposit limit is reached to its cap or not
function _verifyDepositLimit(address _l1Token, address _depositor, uint256 _amount, bool _claiming) internal {
IAllowList.Deposit memory limitData = IAllowList(allowList).getTokenDepositLimitData(_l1Token);
if (!limitData.depositLimitation) return; // no deposit limitation is placed for this token

if (_claiming) {
totalDepositedAmountPerUser[_l1Token][_depositor] -= _amount;
} else {
require(totalDepositedAmountPerUser[_l1Token][_depositor] + _amount <= limitData.depositCap, "d1");
totalDepositedAmountPerUser[_l1Token][_depositor] += _amount;
}
}

/// @return The L2 token address that would be minted for deposit of the given L1 token
function l2TokenAddress(address _l1Token) public view returns (address) {
bytes32 constructorInputHash = keccak256(abi.encode(address(l2TokenBeacon), ""));
Expand Down
14 changes: 4 additions & 10 deletions l1-contracts/contracts/bridge/L1WethBridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,9 @@ import "./interfaces/IL2WethBridge.sol";
import "./interfaces/IL2Bridge.sol";
import "./interfaces/IWETH9.sol";
import "../zksync/interfaces/IZkSync.sol";
import "../common/interfaces/IAllowList.sol";

import "./libraries/BridgeInitializationHelper.sol";

import "../common/AllowListed.sol";
import "../common/libraries/UnsafeBytes.sol";
import "../common/ReentrancyGuard.sol";
import "../common/libraries/L2ContractHelper.sol";
Expand All @@ -34,7 +32,7 @@ import "../vendor/AddressAliasHelper.sol";
/// @dev For withdrawals, the contract receives ETH from the L2 WETH bridge contract, wraps it into
/// WETH, and sends the WETH to the L1 recipient.
/// @dev The `L1WethBridge` contract works in conjunction with its L2 counterpart, `L2WethBridge`.
contract L1WethBridge is IL1Bridge, AllowListed, ReentrancyGuard {
contract L1WethBridge is IL1Bridge, ReentrancyGuard {
using SafeERC20 for IERC20;

/// @dev Event emitted when ETH is received by the contract.
Expand All @@ -43,9 +41,6 @@ contract L1WethBridge is IL1Bridge, AllowListed, ReentrancyGuard {
/// @dev The address of the WETH token on L1
address payable public immutable l1WethAddress;

/// @dev The smart contract that manages the list with permission to call contract functions
IAllowList public immutable allowList;

/// @dev zkSync smart contract that is used to operate with L2 via asynchronous L2 <-> L1 communication
IZkSync public immutable zkSync;

Expand All @@ -61,10 +56,9 @@ contract L1WethBridge is IL1Bridge, AllowListed, ReentrancyGuard {

/// @dev Contract is expected to be used as proxy implementation.
/// @dev Initialize the implementation to prevent Parity hack.
constructor(address payable _l1WethAddress, IZkSync _zkSync, IAllowList _allowList) reentrancyGuardInitializer {
constructor(address payable _l1WethAddress, IZkSync _zkSync) reentrancyGuardInitializer {
l1WethAddress = _l1WethAddress;
zkSync = _zkSync;
allowList = _allowList;
}

/// @dev Initializes a contract bridge for later use. Expected to be used in the proxy
Expand Down Expand Up @@ -163,7 +157,7 @@ contract L1WethBridge is IL1Bridge, AllowListed, ReentrancyGuard {
uint256 _l2TxGasLimit,
uint256 _l2TxGasPerPubdataByte,
address _refundRecipient
) external payable nonReentrant senderCanCallFunction(allowList) returns (bytes32 txHash) {
) external payable nonReentrant returns (bytes32 txHash) {
require(_l1Token == l1WethAddress, "Invalid L1 token address");
require(_amount != 0, "Amount cannot be zero");

Expand Down Expand Up @@ -236,7 +230,7 @@ contract L1WethBridge is IL1Bridge, AllowListed, ReentrancyGuard {
uint16 _l2TxNumberInBatch,
bytes calldata _message,
bytes32[] calldata _merkleProof
) external nonReentrant senderCanCallFunction(allowList) {
) external nonReentrant {
require(!isWithdrawalFinalized[_l2BatchNumber][_l2MessageIndex], "Withdrawal is already finalized");

(address l1WethWithdrawReceiver, uint256 amount) = _parseL2EthWithdrawalMessage(_message);
Expand Down
Loading

0 comments on commit 92fa800

Please sign in to comment.