As this is not a full "bug-code issue", I will not put the typical "Impact-POC-RMS" pattern. The underlying issue is that the L2ERC20Bridge is deploying and linking tokens without taking into account their logic, that is, blacklisting, fee-on-transfer, rebasing... this example is the most dangerous IMO, as it affects a huge amount of money that is in production right now.
Intro
Circle and Tether do back the two most popular stablecoins in the world, namely USDC and USDT. One of the main characteristics that differentiates them from other tokens is that they have a blacklisting functionality, that is, they can block hackers and bad actors from using "their" tokens (I guess it is done to prevent law issues in which Circle or Tether "back" fraudulent or illegal activity, as those stablecoins are overcollateralized with fiat currency in their hands so, in practice, hackers and bad actors would be using Circle's or Tether's money).
Because of this, their counterparts on many L2 do have such a functionality to avoid bad actors from "laundering" their fraudulent money by bridging it to other layers (see on Polygon or Arbitrum, for example). However, zkSync Era does not follow this so MatterLabs may incur in law issues with Circle and Tether because of that, as "their product" has been "modified" (knowingly or unknowingly) to "avoid corporate decisions" and is being used in the wild "as is".
What
Let's review the bridging of ERC20 tokens from a high level:
ANY user can deposit ANY ERC20 compatible token by calling the L1ERC20Bridge, function deposit, which locks the tokens on the bridge and sends a request to the operator with the next token metadata retrieved from the token contract in Ethereum:
The request is sent and the bootloader executes the transaction by calling finalizeDeposit on the L2ERC20Bridge contract. If the given token is not registered as known, it is deployed as an L2StandardERC20 token, without taking into account the actual bytecode in Ethereum (as it is not passed in the metadata above):
function finalizeDeposit(
address _l1Sender,
address _l2Receiver,
address _l1Token,
uint256 _amount,
bytes calldata _data
) external payable override {
...
address expectedL2Token = l2TokenAddress(_l1Token);
address currentL1Token = l1TokenAddress[expectedL2Token];
if (currentL1Token == address(0)) { // not registered as know
address deployedToken = _deployL2Token(_l1Token, _data); // deploys a beacon proxy and the mimic token
require(deployedToken == expectedL2Token, "mt");
l1TokenAddress[expectedL2Token] = _l1Token; // link its address with its L1 counterpart (unmodifiable)
}
...
}
If we see the code of the L2standardERC20 token, it is just a dummy clone of its Ethereum counterpart, that is, it has the above metadata and the transfer/mint/burn/etc functionality of a typical OpenZeppelin ERC20Upgradeable token (not gonna paste the full code here, go read the code by yourself). That means no blacklisting functionality, nor rebasing, nor fee-on-transfer... (that's another issue).
As the bridge stores the relation between the l1Token with the newly deployed token inside the l1TokenAddress mapping and there is no way to update it, even if Circle or Tether deploys their own tokens in zkSync Era with the correct functionalities, the link between their L1 counterpart is already done so the deployed bridge won't be able to "re-link" the Ethereum USDC/USDT address with the correct one. This is a big issue as, right now, there are around 109M USDC and 9.5M USDT locked in the L1ERC20Bridge (see here, which can be freely used by anyone on zkSync Era, as their counterparts on zkSync Era are simple L2StandardERC20 tokens, so the impacts below.
Impacts
Hacker's POV
A hacker exploits a protocol for a huge amount of money.
As he does not want their "bounty" to lose value over time (typical bear market things) he tries to convert his stolen funds to any stablecoin with enough liquidity, that is, USDC or USDT (DAI is there but, whatever).
Before he is blacklisted, he bridges all the swapped USDC/USDT to zkSync Era through the already deployed bridge at address 0x57891966931Eb4Bb6FB81430E6cE0A03AAbDe063 (the one in scope).
Their funds are bridged and the USDC counterpart deployed at address 0x3355df6D4c9C3035724Fd0e3914dE96A5a83aaf4 on zkSync Era (from here) receives them and updates the balance of the hacker (the same goes for USDT).
As it is an L2StandardERC20 token, without blacklisting functionality, the hacker can use all the stolen funds however he wants, and he will not suffer from price fluctuations as USDC/USDT is backed by others (kind of being a free-rider).
Circle/Tether's POV
I don't have time to read the legal terms or any US laws they are subject to. However, "using their product" like it's used right now (see the locked amounts and the transactions being made), which have been "modified" (knowingly or unknowingly) to "avoid corporate decisions" about their "own products" makes the scenario of law issues against MatterLabs real (although remote AF).
Moreover, I haven't read much of the case against TornadoCash by OFAC but, as things are going RN, if hackers ever launder their stolen tokens by bridging them to zkSync Era (that is, avoid sanctions and be able to safeguard and use their bounty without losing value), it may be possible to suffer from law issues which could harm the future of MatterLabs.
Lines of code
https://github.com/code-423n4/2023-10-zksync/blob/1fb4649b612fac7b4ee613df6f6b7d921ddd6b0d/code/contracts/zksync/contracts/bridge/L2StandardERC20.sol#L46 https://github.com/code-423n4/2023-10-zksync/blob/1fb4649b612fac7b4ee613df6f6b7d921ddd6b0d/code/contracts/zksync/contracts/bridge/L2ERC20Bridge.sol#L76-L80
Vulnerability details
As this is not a full "bug-code issue", I will not put the typical "Impact-POC-RMS" pattern. The underlying issue is that the
L2ERC20Bridge
is deploying and linking tokens without taking into account their logic, that is, blacklisting, fee-on-transfer, rebasing... this example is the most dangerous IMO, as it affects a huge amount of money that is in production right now.Intro
Circle and Tether do back the two most popular stablecoins in the world, namely
USDC
andUSDT
. One of the main characteristics that differentiates them from other tokens is that they have a blacklisting functionality, that is, they can block hackers and bad actors from using "their" tokens (I guess it is done to prevent law issues in which Circle or Tether "back" fraudulent or illegal activity, as those stablecoins are overcollateralized with fiat currency in their hands so, in practice, hackers and bad actors would be using Circle's or Tether's money).Because of this, their counterparts on many L2 do have such a functionality to avoid bad actors from "laundering" their fraudulent money by bridging it to other layers (see on Polygon or Arbitrum, for example). However, zkSync Era does not follow this so MatterLabs may incur in law issues with Circle and Tether because of that, as "their product" has been "modified" (knowingly or unknowingly) to "avoid corporate decisions" and is being used in the wild "as is".
What
Let's review the bridging of ERC20 tokens from a high level:
L1ERC20Bridge, lines 240 to 245
bootloader
executes the transaction by callingfinalizeDeposit
on theL2ERC20Bridge
contract. If the given token is not registered as known, it is deployed as an L2StandardERC20 token, without taking into account the actual bytecode in Ethereum (as it is not passed in the metadata above):L2ERC20Bridge, lines 63 to 88
If we see the code of the
L2standardERC20
token, it is just a dummy clone of its Ethereum counterpart, that is, it has the above metadata and the transfer/mint/burn/etc functionality of a typical OpenZeppelinERC20Upgradeable
token (not gonna paste the full code here, go read the code by yourself). That means no blacklisting functionality, nor rebasing, nor fee-on-transfer... (that's another issue).As the bridge stores the relation between the
l1Token
with the newly deployed token inside thel1TokenAddress
mapping and there is no way to update it, even if Circle or Tether deploys their own tokens in zkSync Era with the correct functionalities, the link between their L1 counterpart is already done so the deployed bridge won't be able to "re-link" the Ethereum USDC/USDT address with the correct one. This is a big issue as, right now, there are around 109M USDC and 9.5M USDT locked in theL1ERC20Bridge
(see here, which can be freely used by anyone on zkSync Era, as their counterparts on zkSync Era are simpleL2StandardERC20
tokens, so the impacts below.Impacts
Hacker's POV
L2StandardERC20
token, without blacklisting functionality, the hacker can use all the stolen funds however he wants, and he will not suffer from price fluctuations as USDC/USDT is backed by others (kind of being a free-rider).Circle/Tether's POV
I don't have time to read the legal terms or any US laws they are subject to. However, "using their product" like it's used right now (see the locked amounts and the transactions being made), which have been "modified" (knowingly or unknowingly) to "avoid corporate decisions" about their "own products" makes the scenario of law issues against MatterLabs real (although remote AF).
Moreover, I haven't read much of the case against TornadoCash by OFAC but, as things are going RN, if hackers ever launder their stolen tokens by bridging them to zkSync Era (that is, avoid sanctions and be able to safeguard and use their bounty without losing value), it may be possible to suffer from law issues which could harm the future of MatterLabs.
Assessed type
Other