Security and best practices
Before diving into development on Validium, it's crucial to consider the following recommendations. These best practices will help you optimize your code, ensure security, and align with the unique characteristics of Validium.
Use call
over .send
or .transfer
call
over .send
or .transfer
Avoid using payable(addr).send(x)
/payable(addr).transfer(x)
because the 2300 gas stipend may not be enough for such calls, especially if it involves state changes that require a large amount of L2 gas for data. Instead, we recommend using call
.
Instead of:
Use:
This converts the send
/transfer
functionality to call
and avoids potential security risks outlined here..
While .call
offers more flexibility compared to .send
or .transfer
, developers should be aware that .call
does not provide the same level of reentrancy protection as .transfer
/.send
. It's crucial to adhere to best practices like the checks-effects-interactions pattern and/or use reentrancy guard protection to secure your contracts against reentrancy attacks. It can help ensure the robustness and security of your smart contracts on the ZKSync VM, even under unexpected conditions.
Use the proxy pattern at the early stage of the protocol
Validium is based on the zk-friendly VM. Thus, we offer a dedicated compiler responsible for transforming conventional Solidity and Vyper code into zkEVM bytecode.
While we have extensive test coverage to ensure EVM compatibility, issues may still appear. We will implement the patches for these in a timely manner.
To integrate a compiler bug fix, you need to recompile and upgrade your smart contract. We recommend using the Proxy pattern for a few months after your first deployment on Validium, even if you plan to migrate to an immutable contract in the future.
Do not rely on EVM gas logic
Validium has a distinctive gas logic compared to Ethereum. There are two main drivers:
We have a state-diff-based data availability, which means that the price for the execution depends on the L1 gas price.
ZKsync VM has a different set of computational trade-offs compared to the standard computational model. In practice, this means that the price for opcodes is different to Ethereum. Also, zkEVM contains a different set of opcodes under the hood and so the “gas” metric of the same set of operations may be different on Validium and on Ethereum.
Our fee model is being constantly improved and so it is highly recommended NOT to hardcode any constants since the fee model changes in the future might be breaking for this constant.
gasPerPubdataByte
should be taken into account in development
gasPerPubdataByte
should be taken into account in developmentDue to the state diff-based fee model of Validium, every transaction includes a constant called gasPerPubdataByte
.
Presently, the operator has control over this value. However, in EIP712 transactions, users also sign an upper bound on this value, but the operator is free to choose any value up to that upper bound. Note, that even if the value is chosen by the protocol, it still fluctuates based on the L1 gas price. Therefore, relying solely on gas is inadequate.
A notable example is a Gnosis Safe’s execTransaction
method:
While the contract does enforce the correct gasleft()
, it does not enforce the correct gasPerPubdata
, since there was no such parameter on Ethereum. This means that a malicious user could call this wallet when the gasPerPubdata
is high and make the transaction fail, hence making it spend artificially more gas than required.
This is the case for all relayer-like logic ported directly from Ethereum and so if you see your code relying on logic like “the user should provide at X gas”, then the gasPerPubdata
should be also taken into account on Validium.
For now, Validium operators use honest values for ETH L1 price and gasPerPubdata
, so it should not be an issue if enough margin is added to the estimated gas. In order to prepare for the future decentralization of Validium, it is imperative that you update your contract.
Use native account abstraction over ecrecover
for validation
ecrecover
for validationUse Validium's native account abstraction support for signature validation instead of this function.
We recommend not relying on the fact that an account has an ECDSA private key, since the account may be governed by multisig and use another signature scheme.
Read more about Validium Account Abstraction support.
Use local testing environment
For optimal development and testing of your contracts, it is highly recommended to perform local testing before deploying them to the mainnet. Local testing allows you to test your contracts in a controlled environment, providing benefits such as reduced network latency and cost.
We provide two different testing environments designed for local testing purposes. These tools allow you to simulate the Validium network locally, enabling you to validate your contracts effectively.
By incorporating local testing into your development workflow, you can effectively verify the behavior and functionality of your contracts in a controlled environment, ensuring a smooth deployment process to the mainnet.
For detailed instructions on configuring the local testing environment and performing tests using Mocha and Chai, refer to the dedicated Testing page.
Last updated