Skip to content

Commit

Permalink
Remove allow list (#77)
Browse files Browse the repository at this point in the history
Co-authored-by: Stanislav Breadless <[email protected]>
  • Loading branch information
vladbochok and StanislavBreadless authored Nov 21, 2023
1 parent 13435dd commit 52aa57f
Show file tree
Hide file tree
Showing 45 changed files with 54 additions and 1,280 deletions.
28 changes: 0 additions & 28 deletions docs/Overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -260,11 +260,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 @@ -295,26 +290,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!
36 changes: 5 additions & 31 deletions ethereum/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";

import "../zksync/interfaces/IZkSync.sol";
import "../common/interfaces/IAllowList.sol";
import "../common/AllowListed.sol";
import "../common/libraries/UnsafeBytes.sol";
import "../common/libraries/L2ContractHelper.sol";
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,6 @@ 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.
function deposit(
address _l2Receiver,
address _l1Token,
Expand Down Expand Up @@ -180,12 +172,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 +250,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 +264,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 +283,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 +323,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 ethereum/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
140 changes: 0 additions & 140 deletions ethereum/contracts/common/AllowList.sol

This file was deleted.

17 changes: 0 additions & 17 deletions ethereum/contracts/common/AllowListed.sol

This file was deleted.

Loading

0 comments on commit 52aa57f

Please sign in to comment.