Today I’m testing my codes in the zkSync 2.0 testnet which is compatible with Solidity contracts. However, I found that some codes returned bad data and after short investigating and testing, here are the results.
The problems mentioned in this article is not in the Known issues according to the docs:
There are two common ways to check whether an address is an existing contract.
assembly
uint256 size;
assembly { size := extcodesize(address) }
return size > 0;
code.length
address.code.length > 0;
Both usages could be seen on the most used OpenZeppelin library:
However, both usages are broken in the zkSync 2.0 testnet. Applying the check to arbitrary addresses will always return true.
For example with the following codes:
Solidity
function isContractAssembly(address addr) public view returns (bool) {
uint256 size;
assembly { size := extcodesize(addr) }
return size > 0;
}
function isContractCodeLength(address addr) public view returns (bool) {
return addr.code.length > 0;
}
Account
I generated a fresh empty account to test, please do not use it to store funds.
address:
0xbE67e48CDEB9424715e9A4eB83B86Dab9D42fB63
privateKey:
7c70e3e7ade2bca3f93f624af00a0f78068c2f5ad7f1dc63bb83c3bc0ca9b608
JavaScript with ethers.js
const isContract = await testContract.isContract('0xbE67e48CDEB9424715e9A4eB83B86Dab9D42fB63');
const isContractCodeLength = await testContract.isContractCodeLength('0xbE67e48CDEB9424715e9A4eB83B86Dab9D42fB63');
Both of isContract and isContractCodeLength is true. However, deploying the same code to the Polygon network with the same testing codes, the results are both false.
Another important part is calling the balanceOf method of ERC20 tokens. It seems to work well with existing tokens such as ETH, but when trying to get account balance from not existing (yet) tokens will return bad data.
It’s worth noting that according to the docs, ERC20 tokens deposited from the mainnet will have the same address as its mainnet address. However, the bad data could be returned from both mainnet token addresses or fully empty accounts (EOA).
Solidity
function balanceOf(address erc20, address account) external view returns (uint256) {
return IERC20(erc20).balanceOf(account);
}
JavaScript with ethers.js
const mainnetDAI = '0x84c3766CCFCc1771b712E80361672faD327b735b';
const balanceOf = await testContract.balanceOfUnchecked(mainnetDAI, account);
The mainnet address of DAI is not (yet) a contract in the zkSync 2.0 testnet, however, it will return a balance (the bad data). The data seems to be a random value but for different addresses, the data are the same (in hex and decimal):
0x70a082310000000000000000000000006544df975cf58a0b2c9a361a8db2e00d
50942633119752846454219349998365661925743347005834525140342
888893659768610829
Replacing the mainnet DAI address with arbitrary addresses even EOA will return the same data. The same contract and testing in the Polygon network work as intended (the request are reverted).
Does always return bad data for arbitrary not existing functions or only balanceOf? I tried to call totalSupply() however it got reverted. It’s not pretty clear yet whether it works only with balanceOf(address) or affects other functions too.
This is just very simple testing about this and I believe it is worth more testing and investigating. You could do this by yourself if you are interested. Here are the deployed contracts and codes I used:
ERC20ConsistentTest (zkSync)
0xb4eBf77DAC2998E647F1637aCd2A86149F3D5A78
ERC20ConsistentTest (Polygon)
0xCc1ef95Af1fB6835b6EA42AB1CE7Eddc8948723B
ABI for ethers.js
const abi = [
"function balanceOf(address erc20, address account) external view returns (bool success, uint256 balance)",
"function balanceOfUnchecked(address erc20, address account) external view returns (uint256)",
"function totalSupply(address erc20) external view returns (uint256)",
"function transferFrom(address erc20, address account) external returns (bool success)",
"function isContract(address erc20) public view returns (bool)",
"function isContractCodeLength(address erc20) public view returns (bool)"
];
Solidity code
https://gist.github.com/cakoyo/724ab9f18e3abb9746e71c117e999494
env
Polygon RPC
https://polygon-rpc.com
zkSync 2.0 testnet RPC
https://zksync2-testnet.zksync.dev
solidity version
0.8.12
https://v2-docs.zksync.io/dev/guide/hello-world.html#prerequisites
You can reference this tutorial to develop on zkSync.
Thanks for reading!
Donate: 0x62B8c9b9967D444cb2ca8920ED09044393cc80F6
discord Sotr#8761