Skip to content

Commit 1725a57

Browse files
committed
L-01 Custom Gas Tokens Can Get Stuck In HubPool
Signed-off-by: bennett <[email protected]>
1 parent f6f8807 commit 1725a57

File tree

1 file changed

+23
-19
lines changed

1 file changed

+23
-19
lines changed

contracts/chain-adapters/ZkStack_CustomGasToken_Adapter.sol

+23-19
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,13 @@ contract ZkStack_CustomGasToken_Adapter is AdapterInterface, CircleCCTPAdapter {
181181
uint256 amount,
182182
address to
183183
) external payable override {
184+
// The Hub Pool will always bridge via CCTP to a ZkStack network if CCTP is enabled for that network. Therefore, we can short-circuit ZkStack-specific logic
185+
// like pulling custom gas or getting the shared bridge address if CCTP is enabled and we are bridging USDC.
186+
if (l1Token == address(usdcToken) && _isCCTPEnabled()) {
187+
_transferUsdc(to, amount);
188+
emit TokensRelayed(l1Token, l2Token, amount, to);
189+
return;
190+
}
184191
// A bypass proxy seems to no longer be needed to avoid deposit limits. The tracking of these limits seems to be deprecated.
185192
// See: https://github.com/matter-labs/era-contracts/blob/bce4b2d0f34bd87f1aaadd291772935afb1c3bd6/l1-contracts/contracts/bridge/L1ERC20Bridge.sol#L54-L55
186193
uint256 txBaseCost = _pullCustomGas(L2_GAS_LIMIT);
@@ -224,25 +231,22 @@ contract ZkStack_CustomGasToken_Adapter is AdapterInterface, CircleCCTPAdapter {
224231
})
225232
);
226233
} else if (l1Token == address(usdcToken)) {
227-
if (_isCCTPEnabled()) {
228-
_transferUsdc(to, amount);
229-
} else {
230-
IERC20(CUSTOM_GAS_TOKEN).forceApprove(USDC_SHARED_BRIDGE, txBaseCost);
231-
IERC20(l1Token).forceApprove(USDC_SHARED_BRIDGE, amount);
232-
txHash = BRIDGE_HUB.requestL2TransactionTwoBridges(
233-
BridgeHubInterface.L2TransactionRequestTwoBridgesOuter({
234-
chainId: CHAIN_ID,
235-
mintValue: txBaseCost,
236-
l2Value: 0,
237-
l2GasLimit: L2_GAS_LIMIT,
238-
l2GasPerPubdataByteLimit: L1_GAS_TO_L2_GAS_PER_PUB_DATA_LIMIT,
239-
refundRecipient: L2_REFUND_ADDRESS,
240-
secondBridgeAddress: USDC_SHARED_BRIDGE,
241-
secondBridgeValue: 0,
242-
secondBridgeCalldata: _secondBridgeCalldata(to, l1Token, amount)
243-
})
244-
);
245-
}
234+
// Since we already checked if we are bridging USDC via CCTP, if this conditional is hit, then we must be bridging USDC via the `USDC_SHARED_BRIDGE`.
235+
IERC20(CUSTOM_GAS_TOKEN).forceApprove(USDC_SHARED_BRIDGE, txBaseCost);
236+
IERC20(l1Token).forceApprove(USDC_SHARED_BRIDGE, amount);
237+
txHash = BRIDGE_HUB.requestL2TransactionTwoBridges(
238+
BridgeHubInterface.L2TransactionRequestTwoBridgesOuter({
239+
chainId: CHAIN_ID,
240+
mintValue: txBaseCost,
241+
l2Value: 0,
242+
l2GasLimit: L2_GAS_LIMIT,
243+
l2GasPerPubdataByteLimit: L1_GAS_TO_L2_GAS_PER_PUB_DATA_LIMIT,
244+
refundRecipient: L2_REFUND_ADDRESS,
245+
secondBridgeAddress: USDC_SHARED_BRIDGE,
246+
secondBridgeValue: 0,
247+
secondBridgeCalldata: _secondBridgeCalldata(to, l1Token, amount)
248+
})
249+
);
246250
} else {
247251
// An ERC20 that is not WETH and not the custom gas token.
248252
IERC20(CUSTOM_GAS_TOKEN).forceApprove(sharedBridge, txBaseCost);

0 commit comments

Comments
 (0)