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

Fix non native tokens #12

Closed
wants to merge 3 commits into from
Closed
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
57 changes: 40 additions & 17 deletions ethereum/contracts/bridge/L1ERC20Bridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -149,9 +149,18 @@ contract L1ERC20Bridge is IL1Bridge, IL1BridgeLegacy, AllowListed, ReentrancyGua
address _l1Token,
uint256 _amount,
uint256 _l2TxGasLimit,
uint256 _l2TxGasPerPubdataByte
uint256 _l2TxGasPerPubdataByte,
uint256 _l2MaxFee
) external payable returns (bytes32 l2TxHash) {
l2TxHash = deposit(_l2Receiver, _l1Token, _amount, _l2TxGasLimit, _l2TxGasPerPubdataByte, address(0));
l2TxHash = deposit(
_l2Receiver,
_l1Token,
_amount,
_l2TxGasLimit,
_l2TxGasPerPubdataByte,
address(0),
_l2MaxFee
);
}

/// @notice Initiates a deposit by locking funds on the contract and sending the request
Expand All @@ -162,6 +171,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
/// @param _refundRecipient The address on L2 that will receive the refund for the transaction.
/// @param _l2MaxFee The max fee to be paid in L2.
/// @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.
Expand All @@ -182,37 +192,50 @@ contract L1ERC20Bridge is IL1Bridge, IL1BridgeLegacy, AllowListed, ReentrancyGua
uint256 _amount,
uint256 _l2TxGasLimit,
uint256 _l2TxGasPerPubdataByte,
address _refundRecipient
address _refundRecipient,
uint256 _l2MaxFee
) public payable nonReentrant senderCanCallFunction(allowList) 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);
uint256 amount = validateAndExtractAmount(_l1Token, _amount);

l2TxHash = _getRefundRecipientAndRequestL2Transaction(_refundRecipient, _l2MaxFee, _l2Receiver, _l1Token, _l2TxGasLimit, _l2TxGasPerPubdataByte, amount);
// 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);
}

function _getRefundRecipientAndRequestL2Transaction(address _refundRecipient, uint256 _l2MaxFee, address _l2Receiver, address _l1Token, uint256 _l2TxGasLimit, uint256 _l2TxGasPerPubdataByte, uint256 amount) internal returns (bytes32) {
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.
// Otherwise, the refund will be sent to the specified address.
// If the recipient is a contract on L1, the address alias will be applied.
address refundRecipient = _refundRecipient;
if (_refundRecipient == address(0)) {
refundRecipient = msg.sender != tx.origin ? AddressAliasHelper.applyL1ToL2Alias(msg.sender) : msg.sender;
}
l2TxHash = zkSync.requestL2Transaction{value: msg.value}(
address refundRecipient = _getRefundRecipient(_refundRecipient);

return zkSync.requestL2Transaction{value: msg.value}(
l2Bridge,
0, // L2 msg.value
0,
_l2MaxFee,
l2TxCalldata,
_l2TxGasLimit,
_l2TxGasPerPubdataByte,
new bytes[](0),
refundRecipient
);
}

// Save the deposited amount to claim funds on L1 if the deposit failed on L2
depositAmount[msg.sender][_l1Token][l2TxHash] = amount;
function validateAndExtractAmount(address _l1Token, uint256 _amount) internal returns (uint256 amount) {
require(_amount != 0, "2T"); // empty deposit amount
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);
}

emit DepositInitiated(l2TxHash, msg.sender, _l2Receiver, _l1Token, amount);
// Refund recipient logic
function _getRefundRecipient(address _refundRecipient) internal view returns (address) {
return
_refundRecipient == address(0)
? (msg.sender != tx.origin ? AddressAliasHelper.applyL1ToL2Alias(msg.sender) : msg.sender)
: _refundRecipient;
}

/// @dev Transfers tokens from the depositor address to the smart contract address
Expand Down
5 changes: 3 additions & 2 deletions ethereum/contracts/bridge/L1WethBridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,8 @@ contract L1WethBridge is IL1Bridge, AllowListed, ReentrancyGuard {
uint256 _amount,
uint256 _l2TxGasLimit,
uint256 _l2TxGasPerPubdataByte,
address _refundRecipient
address _refundRecipient,
uint256 _l2MaxFee
) external payable nonReentrant senderCanCallFunction(allowList) returns (bytes32 txHash) {
require(_l1Token == l1WethAddress, "Invalid L1 token address");
require(_amount != 0, "Amount cannot be zero");
Expand All @@ -188,7 +189,7 @@ contract L1WethBridge is IL1Bridge, AllowListed, ReentrancyGuard {
txHash = zkSync.requestL2Transaction{value: _amount + msg.value}(
l2Bridge,
_amount,
0,
_l2MaxFee,
l2TxCalldata,
_l2TxGasLimit,
_l2TxGasPerPubdataByte,
Expand Down
3 changes: 2 additions & 1 deletion ethereum/contracts/bridge/interfaces/IL1Bridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ interface IL1Bridge {
uint256 _amount,
uint256 _l2TxGasLimit,
uint256 _l2TxGasPerPubdataByte,
address _refundRecipient
address _refundRecipient,
uint256 _l2MaxFee
) external payable returns (bytes32 txHash);

function claimFailedDeposit(
Expand Down
3 changes: 2 additions & 1 deletion ethereum/contracts/bridge/interfaces/IL1BridgeLegacy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ interface IL1BridgeLegacy {
address _l1Token,
uint256 _amount,
uint256 _l2TxGasLimit,
uint256 _l2TxGasPerPubdataByte
uint256 _l2TxGasPerPubdataByte,
uint256 _l2MaxFee
) external payable returns (bytes32 txHash);
}
1 change: 0 additions & 1 deletion ethereum/scripts/deploy-erc20.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ async function deployToken(token: TokenDescription, wallet: Wallet): Promise<Tok
if (token.implementation !== "WETH9") {
await erc20.mint(wallet.address, parseEther("30000000000000000"));
await erc20.approve(process.env.CONTRACTS_DIAMOND_PROXY_ADDR, parseEther("30000000000000000"));

}
for (let i = 0; i < 10; ++i) {
const testWallet = Wallet.fromMnemonic(ethTestConfig.test_mnemonic as string, "m/44'/60'/0'/0/" + i).connect(
Expand Down
2 changes: 1 addition & 1 deletion ethereum/scripts/deploy-weth-bridges.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ async function main() {
? new Wallet(cmd.privateKey, provider)
: Wallet.fromMnemonic(
process.env.MNEMONIC ? process.env.MNEMONIC : ethTestConfig.mnemonic,
"m/44'/60'/0'/0/0"
"m/44'/60'/0'/0/0"
).connect(provider);
console.log(`Using deployer wallet: ${deployWallet.address}`);

Expand Down
2 changes: 1 addition & 1 deletion ethereum/scripts/initialize-bridges.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ async function main() {
? new Wallet(cmd.privateKey, provider)
: Wallet.fromMnemonic(
process.env.MNEMONIC ? process.env.MNEMONIC : ethTestConfig.mnemonic,
"m/44'/60'/0'/0/0"
"m/44'/60'/0'/0/0"
).connect(provider);
console.log(`Using deployer wallet: ${deployWallet.address}`);

Expand Down
2 changes: 1 addition & 1 deletion ethereum/scripts/initialize-weth-bridges.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ async function main() {
? new Wallet(cmd.privateKey, provider)
: Wallet.fromMnemonic(
process.env.MNEMONIC ? process.env.MNEMONIC : ethTestConfig.mnemonic,
"m/44'/60'/0'/0/0"
"m/44'/60'/0'/0/0"
).connect(provider);
console.log(`Using deployer wallet: ${deployWallet.address}`);

Expand Down
2 changes: 1 addition & 1 deletion zksync/src/deployL2Weth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ async function main() {
? new Wallet(cmd.privateKey, provider)
: Wallet.fromMnemonic(
process.env.MNEMONIC ? process.env.MNEMONIC : ethTestConfig.mnemonic,
"m/44'/60'/0'/0/0"
"m/44'/60'/0'/0/0"
).connect(provider);
console.log(`Using deployer wallet: ${deployWallet.address}`);

Expand Down