Skip to content

Commit

Permalink
upgraded and compatible with MergeToken
Browse files Browse the repository at this point in the history
  • Loading branch information
zkJoaquin committed Mar 21, 2024
1 parent 59c2811 commit a53627c
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 9 deletions.
91 changes: 82 additions & 9 deletions contracts/zksync/l1-contracts/bridge/L1ERC20Bridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -194,11 +194,74 @@ contract L1ERC20Bridge is IL1Bridge, IL1BridgeLegacy, ReentrancyGuard {
uint256 _l2TxGasPerPubdataByte,
address _refundRecipient
) public payable nonReentrant returns (bytes32 l2TxHash) {
l2TxHash = _deposit(
_l2Receiver,
_l1Token,
_amount,
_l2TxGasLimit,
_l2TxGasPerPubdataByte,
_refundRecipient,
false
);
}

/// @notice Initiates a deposit by locking funds on the contract and sending the request
/// of processing an L2 transaction where merge tokens would be minted
/// @dev If the token is bridged for the first time, the L2 token and merge token contract will be deployed. Note however, that the
/// newly-deployed token does not support any custom logic, i.e. rebase tokens' functionality is not supported.
/// @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 _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
/// @param _refundRecipient The address on L2 that will receive the refund for the transaction.
/// @dev If the L2 deposit finalization transaction fails, the `_refundRecipient` will receive the `_l2Value`.
/// Please note, the contract may change the refund recipient's address to eliminate sending funds to addresses
/// out of control.
/// - If `_refundRecipient` is a contract on L1, the refund will be sent to the aliased `_refundRecipient`.
/// - If `_refundRecipient` is set to `address(0)` and the sender has NO deployed bytecode on L1, the refund will
/// be sent to the `msg.sender` address.
/// - If `_refundRecipient` is set to `address(0)` and the sender has deployed bytecode on L1, the refund will be
/// sent to the aliased `msg.sender` address.
/// @dev The address aliasing of L1 contracts as refund recipient on L2 is necessary to guarantee that the funds
/// are controllable through the Mailbox, since the Mailbox applies address aliasing to the from address for the
/// L2 tx if the L1 msg.sender is a contract. Without address aliasing for L1 contracts as refund recipients they
/// would not be able to make proper L2 tx requests through the Mailbox to use or withdraw the funds from L2, and
/// the funds would be lost.
/// @return l2TxHash The L2 transaction hash of depositToMerge finalization
function depositToMerge(
address _l2Receiver,
address _l1Token,
uint256 _amount,
uint256 _l2TxGasLimit,
uint256 _l2TxGasPerPubdataByte,
address _refundRecipient
) external payable nonReentrant returns (bytes32 l2TxHash) {
l2TxHash = _deposit(
_l2Receiver,
_l1Token,
_amount,
_l2TxGasLimit,
_l2TxGasPerPubdataByte,
_refundRecipient,
true
);
}

function _deposit(
address _l2Receiver,
address _l1Token,
uint256 _amount,
uint256 _l2TxGasLimit,
uint256 _l2TxGasPerPubdataByte,
address _refundRecipient,
bool _toMerge
) internal 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

bytes memory l2TxCalldata = _getDepositL2Calldata(msg.sender, _l2Receiver, _l1Token, amount);
bytes memory l2TxCalldata = _getDepositL2Calldata(msg.sender, _l2Receiver, _l1Token, amount, _toMerge);
// If the refund recipient is not specified, the refund will be sent to the sender of the transaction.
// Otherwise, the refund will be sent to the specified address.
// If the recipient is a contract on L1, the address alias will be applied.
Expand All @@ -218,8 +281,11 @@ contract L1ERC20Bridge is IL1Bridge, IL1BridgeLegacy, ReentrancyGuard {

// Save the deposited amount to claim funds on L1 if the deposit failed on L2
depositAmount[msg.sender][_l1Token][l2TxHash] = amount;

emit DepositInitiated(l2TxHash, msg.sender, _l2Receiver, _l1Token, amount);
if (_toMerge) {
emit DepositToMergeInitiated(l2TxHash, msg.sender, _l2Receiver, _l1Token, amount, _toMerge);
} else {
emit DepositInitiated(l2TxHash, msg.sender, _l2Receiver, _l1Token, amount);
}
}

/// @dev Transfers tokens from the depositor address to the smart contract address
Expand All @@ -237,14 +303,21 @@ contract L1ERC20Bridge is IL1Bridge, IL1BridgeLegacy, ReentrancyGuard {
address _l1Sender,
address _l2Receiver,
address _l1Token,
uint256 _amount
uint256 _amount,
bool _toMerge
) internal view returns (bytes memory txCalldata) {
bytes memory gettersData = _getERC20Getters(_l1Token);

txCalldata = abi.encodeCall(
IL2Bridge.finalizeDeposit,
(_l1Sender, _l2Receiver, _l1Token, _amount, gettersData)
);
if (_toMerge) {
txCalldata = abi.encodeCall(
IL2Bridge.finalizeDepositToMerge,
(_l1Sender, _l2Receiver, _l1Token, _amount, gettersData)
);
} else {
txCalldata = abi.encodeCall(
IL2Bridge.finalizeDeposit,
(_l1Sender, _l2Receiver, _l1Token, _amount, gettersData)
);
}
}

/// @dev Receives and parses (name, symbol, decimals) from the token contract
Expand Down
18 changes: 18 additions & 0 deletions contracts/zksync/l1-contracts/bridge/interfaces/IL1Bridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,15 @@ interface IL1Bridge {
uint256 amount
);

event DepositToMergeInitiated(
bytes32 indexed l2DepositTxHash,
address indexed from,
address indexed to,
address l1Token,
uint256 amount,
bool toMerge
);

event WithdrawalFinalized(address indexed to, address indexed l1Token, uint256 amount);

event ClaimedFailedDeposit(address indexed to, address indexed l1Token, uint256 amount);
Expand All @@ -29,6 +38,15 @@ interface IL1Bridge {
address _refundRecipient
) external payable returns (bytes32 txHash);

function depositToMerge(
address _l2Receiver,
address _l1Token,
uint256 _amount,
uint256 _l2TxGasLimit,
uint256 _l2TxGasPerPubdataByte,
address _refundRecipient
) external payable returns (bytes32 txHash);

function claimFailedDeposit(
address _depositSender,
address _l1Token,
Expand Down
8 changes: 8 additions & 0 deletions contracts/zksync/l1-contracts/bridge/interfaces/IL2Bridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@ interface IL2Bridge {
bytes calldata _data
) external payable;

function finalizeDepositToMerge(
address _l1Sender,
address _l2Receiver,
address _l1Token,
uint256 _amount,
bytes calldata _data
) external payable;

function withdraw(address _l1Receiver, address _l2Token, uint256 _amount) external;

function l1TokenAddress(address _l2Token) external view returns (address);
Expand Down

0 comments on commit a53627c

Please sign in to comment.