Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

upgraded and compatible with MergeToken #85

Merged
merged 1 commit into from
Mar 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading