ERC-4626 vaults have the potential to become an important part of DeFi for the foreseeable future.
As DeFi continues to evolve and mature, a scalable infrastructure and composability are top of mind for developers. ERC, a standardized toolkit for building Ethereum-based applications, has always played an important role. For example, the widely used token standard ERC-20 provides developers with consistent guidelines to contribute to the ecosystem without having to start from scratch. Earlier this year, to encourage cross-compatibility between yielding tokens, the tokenized vault standard ERC-4626 was launched. In addition to this, ERC-4626 addresses pressing composability issues, making protocol integration easier and reducing the chance of errors.
There are already a number of DeFi projects that have adopted the standard in order to improve the composability of their vaults, and we expect wider adoption across the ecosystem. However, tweaking existing vaults does cause some pain, and crucially, certain implementation errors can be exposed and become new targets. Even small mistakes (as small as misunderstandings about the usage interface) can have a significant impact on security and user experience, so more security tools and measures are needed, especially in a more composable DeFi ecosystem.
If a simple error is detected before it is attacked, it can provide a relatively simple solution, ideally checked even before deployment. To this end, we have released ERC-4626 attribute testing for fuzz testing and symbol execution to help vault builders detect standard violations that could break integrations or lead to vulnerabilities. This article explains the motivation problem, describes the detection method, and concludes with some practical recommendations.
Background to the ERC-4626 standard
Launched in March, ERC-4626 is a set of standards for tokenized vaults designed to extend the widely used ERC-20 standard, drive standardization across yield vaults, and ensure composability of applications and protocols that need to interact with them, such as yield aggregators. This means that any application built on the ERC-4626 vault can be easily scaled to work with any other ERC-4626 vault.
Once tokenized, the vault enables users to freely deposit assets to mint vault tokens, which are then redeemed to withdraw principal and interest from the vault. These vault tokens are ERC-20 tokens that can be easily traded or used as collateral to borrow other assets. For example, users can deposit their assets into the Yearn vault to mint yVault tokens, which can then be traded on Uniswap, staked for additional income, or used as collateral for loan agreements.
The logic for generating, distributing earnings, and determining the price of a token may vary depending on the actual situation. To cover as many vaults as possible, the ERC-4626 standard focuses on building user interfaces, with most implementation details undefined. As long as the vault meets the specific requirements of the interface, it is possible to allow changes in the business logic, enabling interoperability across many different types of applications and ERC-4626 vault types.
As more and more tokenized vaults are created, we expect to see them implemented in accordance with the ERC-4626 standard from the start. But we’re currently in some sort of transition, and to be compliant, developers will need to update existing vaults, applications, and protocols in a more composable way, and they also face many complex challenges.
The challenge of standards conformance
Following new standards isn’t always straightforward. Each ERC-4626 vault must faithfully and accurately implement the described standard requirements, otherwise the integration will become increasingly complex in response to different changes. This complexity makes integration inherently error-prone. And because they are not adequately tested for security, they can lead to system vulnerabilities over time.
To safely handle different behaviors, non-ERC-20 standard tokens require many DeFi systems to use additional vaults when performing token transfers. For example, Tether USD requires an additional use of SafeERC-20 to perform token transfers.
This means that any system that interacts with these tokens could become vulnerable if the system is not designed to properly handle “lost returns” situations. These scenarios can introduce a common security trap and increase overall development and maintenance costs. Therefore, compliance with standards is critical not only for individuals, but also for the security of the entire ecosystem, where a single vulnerability in a single system or dependency can cause widespread problems.
Ideally, standards will be explicitly and formally specified, and each implementation can be formally validated against standard specifications. However, in practice, it requires community efforts and requires a certain cost or time cost, which is not easy to achieve in a short period of time.
Identify consistency issues by introducing executable ERC-4626 attributes
As we work toward an ideal state where each vault is formally validated against strict formal specifications, we have written ERC-4626 standard attributes to capture differences in the subtle, easily missed details required by the standard.
To detect potential standard violations in its implementation, developers of tokenized vaults can run tests before deployment. Vault integrators can check if a given vault meets standards before integrating them into their system. For real-time vaults that have been deployed on the mainnet, they can also be tested through mainnet fork testing. To ensure that all system parameters are set correctly, especially in recently deployed or upgraded vaults, it can be useful to test a live vault.
To make the property executable, we write it in Foundry and run it by fuzzer. In order to formally verify that a given feed meets the properties of all possible inputs and conditions, in the future they may also be run by symbolic execution or model checking tools.
Commonality is a top priority when writing, and we want tests that can be applied to various vaults that implement different business logic. We only use public interface functions to make them irrelevant to the implementation details. However, because of this limitation, certain standard requirements involving implementation-specific internal data are omitted from the properties.
For example, the following property corresponds to one of the requirements of the convert To Shares() function, “No change should be displayed based on the caller.”
Given two account addresses and amounts, it causes each account to call convertToShares() with the same amount and ensures that the two return values are equal. This property is independent of the implementation detail convertToShares(). These details vary from vault to vault and must be met by any vault that implements ERC-4626. In this case, you can perform this property by providing a specific input value (for unit testing), many random inputs for fuzz testing, or a symbol value for symbol execution and formal verification. It can also be run locally or against mainnet forks.
Use case: Test rounding the wrong property
For example, rounding errors are a seemingly minor but important type of error that can have some series of effects. In the basic accounting logic of ERC-4626, rounding errors are unavoidable, such as instructions implemented using fixed-point arithmetic, such as calculating the number of assets to mint or the number of assets to be withdrawn. For security reasons, the standard explicitly specifies the preferred rounding direction for each interface function, without specifying a margin of error. Specifically, the deposit() and redeem() functions should return an approximation below the exact value, while the mint() and withdraw() functions should return an approximation above the exact value. For example, if the current stock price (i.e. the number of assets per share) is 2, then deposit()3 wei assets can only mint up to 1 wei tokens (i.e. floor(3/2)), while withdraw()3 wei assets should be at least 2 wei tokens (i.e. ceil(3/2)).
We write rounding-related attributes as independent of the underlying accounting logic and treat them as “black boxes”. Specifically, we formulate them as so-called “round trip” properties, which describe the relationship between two opposite functions. For example, the following attribute states that the extraction of an asset just in custody by minting N shares must burn no less than N shares. In other words, no one can make a profit by repeatedly minting and withdrawing to repeatedly convert assets and vault tokens.
In fact, we found several ERC-4626 vaults on the mainnet that failed to satisfy the above attributes due to rounding errors. This means that anyone can earn satoshi BTC (1 satoshi ~= 0.02 cents at the time of writing) by slowly depleting the vault through simple repeated minting and withdrawal. It is possible to make a profit on a chain with low gas fees such as Fantom, or also when the price rises.
Extensive testing of the ERC-4626 standard
We tested the attributes of around 100 ERC-4626 vaults on mainnet and found that many failed to comply with the standard requirements. The main reason for this is rounding errors. Specifically, the mint() function fails to mint the exact number of shares requested by the function, despite the explicit requirement of the standard. Some of them also emit inconsistent Deposit events where the data recorded differs from the actual generated data, and some vaults are not even minted live at all. Instead, they simply put minting requests into a queue and later batch them as separate transactions.
Although these different behaviors are not exploitable on their own, they can become vulnerable when integrated into other systems that only perform standard behavior. These issues will make vault integration more difficult and may negate some of the effort.
Attribute testing and other actionable steps achieve standard consistency
Strictly following the standards before deployment can prevent different behavior. We hope that our properties and a few additional action items will help those who are developing or integrating ERC-4626 vaults:
- We strongly recommend running attribute tests on your vault. If there are any obvious violations of the standards, the problem will be quickly discovered.
- We also recommend checking our attributes to check your understanding of the standard requirements and adjust the implementation if there are any unintentional discrepancies.
- If the vault must deviate from the standard, we recommend that non-standard behavior be explicitly documented so that others can properly handle these deviations when integrating with the vault.
ERC-4626 vaults have the potential to become an important part of DeFi for the foreseeable future. To maintain composability, both new and existing vaults must follow the standard. New standards will emerge, so now is the perfect time to standardize existing vaults.
As we work toward the ideal state of a unified combination of different vaults, ERC-4626 attribute tests can be run to more easily detect standard violations in vault implementations. Documentation and examples for property testing are publicly available in our Github repository.
Posted by:CoinYuppie，Reprinted with attribution to:https://coinyuppie.com/a16z-introducing-erc-4626-vault-common-properties-test-making-defi-composability-more-secure/
Coinyuppie is an open information publishing platform, all information provided is not related to the views and positions of coinyuppie, and does not constitute any investment and financial advice. Users are expected to carefully screen and prevent risks.