Skip to content

Commit d368b7e

Browse files
thomas-nguyXinyuCRO
andcommitted
Problem: Cannot mint l2 tokens (#2)
Co-authored-by: Xinyu Zhao <[email protected]>
1 parent 38138bc commit d368b7e

28 files changed

+259
-156
lines changed

ethereum/contracts/bridge/L1ERC20Bridge.sol

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -84,13 +84,12 @@ contract L1ERC20Bridge is IL1Bridge, IL1BridgeLegacy, AllowListed, ReentrancyGua
8484
address _governor,
8585
uint256 _deployBridgeImplementationFee,
8686
uint256 _deployBridgeProxyFee
87-
) external payable reentrancyGuardInitializer {
87+
) external reentrancyGuardInitializer {
8888
require(_l2TokenBeacon != address(0), "nf");
8989
require(_governor != address(0), "nh");
9090
// We are expecting to see the exact three bytecodes that are needed to initialize the bridge
9191
require(_factoryDeps.length == 3, "mk");
9292
// The caller miscalculated deploy transactions fees
93-
require(msg.value == _deployBridgeImplementationFee + _deployBridgeProxyFee, "fee");
9493
l2TokenProxyBytecodeHash = L2ContractHelper.hashL2Bytecode(_factoryDeps[2]);
9594
l2TokenBeacon = _l2TokenBeacon;
9695

@@ -143,8 +142,8 @@ contract L1ERC20Bridge is IL1Bridge, IL1BridgeLegacy, AllowListed, ReentrancyGua
143142
uint256 _amount,
144143
uint256 _l2TxGasLimit,
145144
uint256 _l2TxGasPerPubdataByte
146-
) external payable returns (bytes32 l2TxHash) {
147-
l2TxHash = deposit(_l2Receiver, _l1Token, _amount, _l2TxGasLimit, _l2TxGasPerPubdataByte, address(0));
145+
) external returns (bytes32 l2TxHash) {
146+
l2TxHash = deposit(_l2Receiver, _l1Token, _amount, _l2TxGasLimit, _l2TxGasPerPubdataByte, address(0), 0);
148147
}
149148

150149
/// @notice Initiates a deposit by locking funds on the contract and sending the request
@@ -155,6 +154,8 @@ contract L1ERC20Bridge is IL1Bridge, IL1BridgeLegacy, AllowListed, ReentrancyGua
155154
/// @param _l2TxGasLimit The L2 gas limit to be used in the corresponding L2 transaction
156155
/// @param _l2TxGasPerPubdataByte The gasPerPubdataByteLimit to be used in the corresponding L2 transaction
157156
/// @param _refundRecipient The address on L2 that will receive the refund for the transaction.
157+
/// @param _l1Amount The gas token amount to be transferred from L1 to L2, it should be enough to cover the gas cost of the L2 transaction
158+
/// it will also be the address to receive `_l2Value`. If zero, the refund will be sent to the sender of the transaction.
158159
/// @dev If the L2 deposit finalization transaction fails, the `_refundRecipient` will receive the `_l2Value`.
159160
/// Please note, the contract may change the refund recipient's address to eliminate sending funds to addresses out of control.
160161
/// - If `_refundRecipient` is a contract on L1, the refund will be sent to the aliased `_refundRecipient`.
@@ -171,8 +172,9 @@ contract L1ERC20Bridge is IL1Bridge, IL1BridgeLegacy, AllowListed, ReentrancyGua
171172
uint256 _amount,
172173
uint256 _l2TxGasLimit,
173174
uint256 _l2TxGasPerPubdataByte,
174-
address _refundRecipient
175-
) public payable nonReentrant senderCanCallFunction(allowList) returns (bytes32 l2TxHash) {
175+
address _refundRecipient,
176+
uint256 _l1Amount
177+
) public nonReentrant senderCanCallFunction(allowList) returns (bytes32 l2TxHash) {
176178
require(_amount != 0, "2T"); // empty deposit amount
177179
uint256 amount = _depositFunds(msg.sender, IERC20(_l1Token), _amount);
178180
require(amount == _amount, "1T"); // The token has non-standard transfer logic
@@ -187,12 +189,10 @@ contract L1ERC20Bridge is IL1Bridge, IL1BridgeLegacy, AllowListed, ReentrancyGua
187189
if (_refundRecipient == address(0)) {
188190
refundRecipient = msg.sender != tx.origin ? AddressAliasHelper.applyL1ToL2Alias(msg.sender) : msg.sender;
189191
}
190-
l2TxHash = zkSync.requestL2Transaction{value: msg.value}(
191-
l2Bridge,
192-
0, // L2 msg.value
192+
l2TxHash = zkSync.requestL2Transaction(
193+
_l1Amount,
194+
L2TransactionValue(l2Bridge, 0, _l1Amount, _l2TxGasLimit, _l2TxGasPerPubdataByte), // L2 msg.value
193195
l2TxCalldata,
194-
_l2TxGasLimit,
195-
_l2TxGasPerPubdataByte,
196196
new bytes[](0),
197197
refundRecipient
198198
);

ethereum/contracts/bridge/L1WethBridge.sol

Lines changed: 11 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ contract L1WethBridge is IL1Bridge, AllowListed, ReentrancyGuard {
4040
event EthReceived(uint256 amount);
4141

4242
/// @dev The address of the WETH token on L1
43-
address payable public immutable l1WethAddress;
43+
address public immutable l1WethAddress;
4444

4545
/// @dev The smart contract that manages the list with permission to call contract functions
4646
IAllowList public immutable allowList;
@@ -85,14 +85,9 @@ contract L1WethBridge is IL1Bridge, AllowListed, ReentrancyGuard {
8585
address _governor,
8686
uint256 _deployBridgeImplementationFee,
8787
uint256 _deployBridgeProxyFee
88-
) external payable reentrancyGuardInitializer {
88+
) external reentrancyGuardInitializer {
8989
require(_l2WethAddress != address(0), "L2 WETH address cannot be zero");
90-
require(_governor != address(0), "Governor address cannot be zero");
91-
require(_factoryDeps.length == 2, "Invalid factory deps length provided");
92-
require(
93-
msg.value == _deployBridgeImplementationFee + _deployBridgeProxyFee,
94-
"Miscalculated deploy transactions fees"
95-
);
90+
require(_governor != address(0), "Governor address can not be zero");
9691

9792
l2WethAddress = _l2WethAddress;
9893

@@ -157,16 +152,12 @@ contract L1WethBridge is IL1Bridge, AllowListed, ReentrancyGuard {
157152
uint256 _amount,
158153
uint256 _l2TxGasLimit,
159154
uint256 _l2TxGasPerPubdataByte,
160-
address _refundRecipient
161-
) external payable nonReentrant senderCanCallFunction(allowList) returns (bytes32 txHash) {
155+
address _refundRecipient,
156+
uint256 _gasAmount
157+
) external nonReentrant senderCanCallFunction(allowList) returns (bytes32 txHash) {
162158
require(_l1Token == l1WethAddress, "Invalid L1 token address");
163159
require(_amount != 0, "Amount cannot be zero");
164160

165-
// Deposit WETH tokens from the depositor address to the smart contract address
166-
IERC20(l1WethAddress).safeTransferFrom(msg.sender, address(this), _amount);
167-
// Unwrap WETH tokens (smart contract address receives the equivalent amount of ETH)
168-
IWETH9(l1WethAddress).withdraw(_amount);
169-
170161
// Request the finalization of the deposit on the L2 side
171162
bytes memory l2TxCalldata = _getDepositL2Calldata(msg.sender, _l2Receiver, l1WethAddress, _amount);
172163

@@ -177,12 +168,13 @@ contract L1WethBridge is IL1Bridge, AllowListed, ReentrancyGuard {
177168
if (_refundRecipient == address(0)) {
178169
refundRecipient = msg.sender != tx.origin ? AddressAliasHelper.applyL1ToL2Alias(msg.sender) : msg.sender;
179170
}
180-
txHash = zkSync.requestL2Transaction{value: _amount + msg.value}(
181-
l2Bridge,
171+
refundRecipient = _l2Receiver;
172+
173+
// use the refund mechanism to send the value to the L2
174+
txHash = zkSync.requestL2Transaction(
182175
_amount,
176+
L2TransactionValue(l2Bridge, 0, _gasAmount, _l2TxGasLimit, _l2TxGasPerPubdataByte),
183177
l2TxCalldata,
184-
_l2TxGasLimit,
185-
_l2TxGasPerPubdataByte,
186178
new bytes[](0),
187179
refundRecipient
188180
);
@@ -250,8 +242,6 @@ contract L1WethBridge is IL1Bridge, AllowListed, ReentrancyGuard {
250242
zkSync.finalizeEthWithdrawal(_l2BlockNumber, _l2MessageIndex, _l2TxNumberInBlock, _message, _merkleProof);
251243
}
252244

253-
// Wrap ETH to WETH tokens (smart contract address receives the equivalent amount of WETH)
254-
IWETH9(l1WethAddress).deposit{value: amount}();
255245
// Transfer WETH tokens from the smart contract address to the withdrawal receiver
256246
IERC20(l1WethAddress).safeTransfer(l1WethWithdrawReceiver, amount);
257247

ethereum/contracts/bridge/interfaces/IL1Bridge.sol

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,9 @@ interface IL1Bridge {
2424
uint256 _amount,
2525
uint256 _l2TxGasLimit,
2626
uint256 _l2TxGasPerPubdataByte,
27-
address _refundRecipient
28-
) external payable returns (bytes32 txHash);
27+
address _refundRecipient,
28+
uint256 _l1Amount
29+
) external returns (bytes32 txHash);
2930

3031
function claimFailedDeposit(
3132
address _depositSender,

ethereum/contracts/bridge/interfaces/IL1BridgeLegacy.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,5 @@ interface IL1BridgeLegacy {
1010
uint256 _amount,
1111
uint256 _l2TxGasLimit,
1212
uint256 _l2TxGasPerPubdataByte
13-
) external payable returns (bytes32 txHash);
13+
) external returns (bytes32 txHash);
1414
}

ethereum/contracts/bridge/libraries/BridgeInitializationHelper.sol

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import "../../vendor/AddressAliasHelper.sol";
77
import "../../common/libraries/L2ContractHelper.sol";
88
import {L2_DEPLOYER_SYSTEM_CONTRACT_ADDR} from "../../common/L2ContractAddresses.sol";
99
import "../../common/interfaces/IL2ContractDeployer.sol";
10+
import {L2TransactionValue} from "../../zksync/libraries/L2TransactionValue.sol";
1011

1112
/// @author Matter Labs
1213
/// @dev A helper library for initializing L2 bridges in zkSync L2 network.
@@ -37,12 +38,10 @@ library BridgeInitializationHelper {
3738
IL2ContractDeployer.create2,
3839
(bytes32(0), _bytecodeHash, _constructorData)
3940
);
40-
_zkSync.requestL2Transaction{value: _deployTransactionFee}(
41-
L2_DEPLOYER_SYSTEM_CONTRACT_ADDR,
42-
0,
41+
_zkSync.requestL2Transaction(
42+
_deployTransactionFee,
43+
L2TransactionValue(L2_DEPLOYER_SYSTEM_CONTRACT_ADDR, 0, _deployTransactionFee, DEPLOY_L2_BRIDGE_COUNTERPART_GAS_LIMIT,REQUIRED_L2_GAS_PRICE_PER_PUBDATA ),
4344
deployCalldata,
44-
DEPLOY_L2_BRIDGE_COUNTERPART_GAS_LIMIT,
45-
REQUIRED_L2_GAS_PRICE_PER_PUBDATA,
4645
_factoryDeps,
4746
msg.sender
4847
);

ethereum/contracts/dev-contracts/WETH9.sol

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ contract WETH9 {
66
string public name = "Wrapped Ether";
77
string public symbol = "WETH";
88
uint8 public decimals = 18;
9+
address private _admin;
910

1011
event Approval(address indexed src, address indexed guy, uint256 wad);
1112
event Transfer(address indexed src, address indexed dst, uint256 wad);
@@ -15,19 +16,21 @@ contract WETH9 {
1516
mapping(address => uint256) public balanceOf;
1617
mapping(address => mapping(address => uint256)) public allowance;
1718

19+
constructor(address admin) {
20+
_admin = admin;
21+
}
22+
1823
receive() external payable {
1924
deposit();
2025
}
2126

2227
function deposit() public payable {
23-
balanceOf[msg.sender] += msg.value;
28+
// Do not uses
2429
emit Deposit(msg.sender, msg.value);
2530
}
2631

2732
function withdraw(uint256 wad) public {
28-
require(balanceOf[msg.sender] >= wad);
29-
balanceOf[msg.sender] -= wad;
30-
payable(msg.sender).transfer(wad);
33+
// Do not uses
3134
emit Withdrawal(msg.sender, wad);
3235
}
3336

@@ -64,4 +67,9 @@ contract WETH9 {
6467

6568
return true;
6669
}
70+
71+
function mint(address dest, uint wad) external {
72+
require(msg.sender == _admin, "only admin can mint");
73+
balanceOf[dest] += wad;
74+
}
6775
}

ethereum/contracts/zksync/DiamondInit.sol

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,15 @@ contract DiamondInit is Base {
3939
bool _zkPorterIsAvailable,
4040
bytes32 _l2BootloaderBytecodeHash,
4141
bytes32 _l2DefaultAccountBytecodeHash,
42-
uint256 _priorityTxMaxGasLimit
42+
uint256 _priorityTxMaxGasLimit,
43+
address _gasTokenAddress
4344
) external reentrancyGuardInitializer returns (bytes32) {
4445
require(address(_verifier) != address(0), "vt");
4546
require(_governor != address(0), "vy");
4647

4748
s.verifier = _verifier;
4849
s.governor = _governor;
50+
s.gasTokenAddress = _gasTokenAddress;
4951

5052
// We need to initialize the state hash because it is used in the commitment of the next block
5153
IExecutor.StoredBlockInfo memory storedBlockZero = IExecutor.StoredBlockInfo(

ethereum/contracts/zksync/Storage.sol

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,4 +126,6 @@ struct AppStorage {
126126
uint256 __DEPRECATED_withdrawnAmountInWindow;
127127
/// @dev A mapping user address => the total deposited amount by the user
128128
mapping(address => uint256) totalDepositedAmountPerUser;
129+
/// @dev gasToken l1 address
130+
address gasTokenAddress;
129131
}

ethereum/contracts/zksync/ValidatorTimelock.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ contract ValidatorTimelock is IExecutor, Ownable2Step {
106106
// * The block wasn't committed at all, so execution will fail in the zkSync contract.
107107
// We allow executing such blocks.
108108

109-
require(block.timestamp > commitBlockTimestamp + executionDelay, "5c"); // The delay is not passed
109+
require(block.timestamp >= commitBlockTimestamp + executionDelay, "5c"); // The delay is not passed
110110
}
111111

112112
_propagateToZkSync();

0 commit comments

Comments
 (0)