Skip to content

Commit 7886269

Browse files
authored
fix: [M-01] zkSync limits (#328)
* fix: [M-01] zkSync limits Signed-off-by: Matt Rice <matthewcrice32@gmail.com> * remove snake case lint warning Signed-off-by: Matt Rice <matthewcrice32@gmail.com> --------- Signed-off-by: Matt Rice <matthewcrice32@gmail.com>
1 parent bf98ded commit 7886269

File tree

2 files changed

+69
-5
lines changed

2 files changed

+69
-5
lines changed

.solhint.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
"extends": "solhint:recommended",
33
"rules": {
44
"compiler-version": ["error", "^0.8.0"],
5-
"func-visibility": ["warn", { "ignoreConstructors": true }]
5+
"func-visibility": ["warn", { "ignoreConstructors": true }],
6+
"const-name-snakecase": "off"
67
}
78
}

contracts/chain-adapters/ZkSync_Adapter.sol

Lines changed: 67 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,63 @@ interface ZkBridgeLike {
5353
) external payable returns (bytes32 txHash);
5454
}
5555

56+
// Note: this contract just forwards the calls from the HubPool to ZkSync to avoid limits.
57+
// A modified ZKSync_Adapter should be deployed with this address swapped in for all zkSync addresses.
58+
contract LimitBypassProxy is ZkSyncInterface, ZkBridgeLike {
59+
using SafeERC20 for IERC20;
60+
ZkSyncInterface public constant zkSync = ZkSyncInterface(0x32400084C286CF3E17e7B677ea9583e60a000324);
61+
ZkBridgeLike public constant zkErc20Bridge = ZkBridgeLike(0x57891966931Eb4Bb6FB81430E6cE0A03AAbDe063);
62+
63+
function l2TransactionBaseCost(
64+
uint256 _l1GasPrice,
65+
uint256 _l2GasLimit,
66+
uint256 _l2GasPerPubdataByteLimit
67+
) external view returns (uint256) {
68+
return zkSync.l2TransactionBaseCost(_l1GasPrice, _l2GasLimit, _l2GasPerPubdataByteLimit);
69+
}
70+
71+
function requestL2Transaction(
72+
address _contractL2,
73+
uint256 _l2Value,
74+
bytes calldata _calldata,
75+
uint256 _l2GasLimit,
76+
uint256 _l2GasPerPubdataByteLimit,
77+
bytes[] calldata _factoryDeps,
78+
address _refundRecipient
79+
) external payable returns (bytes32 canonicalTxHash) {
80+
return
81+
zkSync.requestL2Transaction{ value: msg.value }(
82+
_contractL2,
83+
_l2Value,
84+
_calldata,
85+
_l2GasLimit,
86+
_l2GasPerPubdataByteLimit,
87+
_factoryDeps,
88+
_refundRecipient
89+
);
90+
}
91+
92+
function deposit(
93+
address _l2Receiver,
94+
address _l1Token,
95+
uint256 _amount,
96+
uint256 _l2TxGasLimit,
97+
uint256 _l2TxGasPerPubdataByte,
98+
address _refundRecipient
99+
) external payable returns (bytes32 txHash) {
100+
IERC20(_l1Token).safeIncreaseAllowance(address(zkErc20Bridge), _amount);
101+
return
102+
zkErc20Bridge.deposit{ value: msg.value }(
103+
_l2Receiver,
104+
_l1Token,
105+
_amount,
106+
_l2TxGasLimit,
107+
_l2TxGasPerPubdataByte,
108+
_refundRecipient
109+
);
110+
}
111+
}
112+
56113
/**
57114
* @notice Contract containing logic to send messages from L1 to ZkSync.
58115
* @dev Public functions calling external contracts do not guard against reentrancy because they are expected to be
@@ -88,7 +145,12 @@ contract ZkSync_Adapter is AdapterInterface {
88145
// redeployed in the event that the following addresses change.
89146

90147
// Main contract used to send L1 --> L2 messages. Fetchable via `zks_getMainContract` method on JSON RPC.
91-
ZkSyncInterface public constant zkSync = ZkSyncInterface(0x32400084C286CF3E17e7B677ea9583e60a000324);
148+
ZkSyncInterface public constant zkSyncMessageBridge = ZkSyncInterface(0x32400084C286CF3E17e7B677ea9583e60a000324);
149+
150+
// Contract used to send ETH to L2. Note: this is the same address as the main contract, but separated to allow
151+
// only this contract to be swapped (leaving the main zkSync contract to be used for messaging).
152+
ZkSyncInterface public constant zkSyncEthBridge = ZkSyncInterface(0x32400084C286CF3E17e7B677ea9583e60a000324);
153+
92154
// Bridges to send ERC20 and ETH to L2. Fetchable via `zks_getBridgeContracts` method on JSON RPC.
93155
ZkBridgeLike public constant zkErc20Bridge = ZkBridgeLike(0x57891966931Eb4Bb6FB81430E6cE0A03AAbDe063);
94156

@@ -117,7 +179,7 @@ contract ZkSync_Adapter is AdapterInterface {
117179
uint256 txBaseCost = _contractHasSufficientEthBalance();
118180

119181
// Returns the hash of the requested L2 transaction. This hash can be used to follow the transaction status.
120-
bytes32 canonicalTxHash = zkSync.requestL2Transaction{ value: txBaseCost }(
182+
bytes32 canonicalTxHash = zkSyncMessageBridge.requestL2Transaction{ value: txBaseCost }(
121183
target,
122184
// We pass no ETH with the call, otherwise we'd need to add to the txBaseCost this value.
123185
0,
@@ -164,7 +226,7 @@ contract ZkSync_Adapter is AdapterInterface {
164226
if (l1Token == address(l1Weth)) {
165227
l1Weth.withdraw(amount);
166228
// We cannot call the standard ERC20 bridge because it disallows ETH deposits.
167-
txHash = zkSync.requestL2Transaction{ value: txBaseCost + amount }(
229+
txHash = zkSyncEthBridge.requestL2Transaction{ value: txBaseCost + amount }(
168230
to,
169231
amount,
170232
"",
@@ -199,7 +261,8 @@ contract ZkSync_Adapter is AdapterInterface {
199261
// https://github.com/matter-labs/era-contracts/blob/6391c0d7bf6184d7f6718060e3991ba6f0efe4a7/ethereum/contracts/zksync/facets/Mailbox.sol#L273
200262
// - priority_fee_per_gas = min(transaction.max_priority_fee_per_gas, transaction.max_fee_per_gas - block.base_fee_per_gas)
201263
// - effective_gas_price = priority_fee_per_gas + block.base_fee_per_gas
202-
return zkSync.l2TransactionBaseCost(tx.gasprice, L2_GAS_LIMIT, L1_GAS_TO_L2_GAS_PER_PUB_DATA_LIMIT);
264+
return
265+
zkSyncMessageBridge.l2TransactionBaseCost(tx.gasprice, L2_GAS_LIMIT, L1_GAS_TO_L2_GAS_PER_PUB_DATA_LIMIT);
203266
}
204267

205268
function _contractHasSufficientEthBalance() internal view returns (uint256 requiredL1CallValue) {

0 commit comments

Comments
 (0)