Általános tulajdonságtesztek az ERC4626 tárolókhoz PlatoBlockchain Data Intelligence. Függőleges keresés. Ai.

Általános tulajdonságtesztek ERC4626 tárolókhoz

As DeFi grows and matures, scalable infrastructure and composability are top of mind for developers. Ethereum Requests for Comments (or ERCs) — standardized toolkits for building Ethereum-based apps, such as the widely used token standard ERC20 — serve the essential role of providing consistent guidelines for developers to contribute to the ecosystem without starting from scratch. Korábban ebben az évben, tokenized vault standard ERC4626 was created to encourage cross-compatibility among yield-bearing tokens. Standardizing implementations details can also address pressing composability issues, making protocol integration easier and ultimately less error-prone.

Several DeFi projects have already fogadott the standard, looking to increase the composability of their vaults, and we anticipate wider adoption throughout the ecosystem. Adapting existing vaults does cause some growing pains, however; critically, certain implementation errors can expose new targets for attack. Even small errors (as small as misinterpreting the standard interface) can have significant consequences for both security and user experience, underscoring the need for more security tools and measures, particularly within a more composable DeFi ecosystem. 

Fortunately, simple errors can have relatively simple solutions if detected well before they’re exploited (and ideally before they’re even deployed). To that end, we released ERC4626 property tests for fuzzing and symbolic execution to help vault builders detect standard violations that may break integrations or lead to vulnerabilities down the line. In this post, we explain the motivating problem, walk through our approach, and conclude with some actionable advice.

First a little background on the ERC4626 standard

Finalized in March, ERC4626 is the standard for tokenized vaults. It was introduced in order to extend the widely used ERC20 standard (currently the base for hundreds of tokens), encourage standardization across yield-bearing vaults, and ensure composability for the apps and protocols (e.g. yield aggregators) that need to interact with them. This means that any app built on an ERC4626 vault can be easily extended to work with any other ERC4626 vault. 

Tokenized vaults allow users to freely deposit assets to mint vault shares, and later redeem those shares to withdraw principal and interest from the vault. These vault shares are ERC20 tokens, and thus can be easily traded or used as collateral to borrow other assets. For example, users can deposit their assets in Yearn vaults to mint yVault tokens, which can then be traded on Uniswap, staked for additional yield, or used as collateral for lending protocols.

The business logic for generating and distributing yield (and determining the share price) may vary across implementations. In order to cover as many vaults as possible (with the goal of making them interoperable vs. identical), the ERC4626 standard focuses on describing the user interface, leaving most of the implementation details unspecified. This allows for variations in business logic as long as the vault meets the specific requirements of the interface, and encourages interoperability across many different kinds of apps and types of ERC4626 vaults.

As more vaults are created, we expect to see them implemented according to the ERC4626 standard from the start; but we’re currently in a somewhat transitional phase, where developers looking to take advantage of greater composability will need to update existing vaults, apps, and protocols to conform with the standard. And as they upgrade, they contend with a number of complexities and challenges. 

The challenges of standard conformance (and the pitfalls of failing to conform)

Following a new standard isn’t always straightforward. Every ERC4626 vault must faithfully (and exactly) implement the standard’s requirements as described. Otherwise, the integration of ERC4626 vaults becomes increasingly complex to account for different variations. This complexity makes integrations inherently error-prone; and because they aren’t sufficiently future proof, they may lead to security vulnerabilities over time.

Non-standard ERC20 tokens (e.g., Tether USD) require many DeFi systems to use an additional library (such as SafeERC20) when performing token transfers to safely deal with diverging behaviors (for example returning nothing when a transfer succeeds instead of returning true). This means that any systems interacting with these tokens could become vulnerable if the system isn’t designed to properly handle cases of “missing returns.” These scenarios can potentially introduce a common security pitfall, and increase overall development and maintenance costs (when factoring in the additional logic and dependencies needed to mitigate issues). Conforming to the standard is therefore critical not only for individual implementations but also for the security of the entire ecosystem. One vulnerability in a single system or dependency can cause widespread issues.

Ideally, standards would be formally specified without ambiguity (e.g., formal specification of ERC20), and every implementation could be formally verified against the standard specification. In practice, however, this isn’t easy to achieve in a short period of time, due the cost and effort required from the community.

Introducing executable ERC4626 properties to identify conformance issues 

As we work toward an ideal state (every vault formally verified against rigorous formal specifications), we’ve written ERC4626 standard ingatlanait to catch discrepancies in subtle, easy-to-miss details of the standard requirements.  

Vault developers can run the tests to detect potential standard violations in their implementations before deployment. And vault integrators can check if the given vaults follow the standard before integrating them into their system. The properties can also be tested against the live vaults already deployed on the mainnet, via mainnet fork testing. Testing live vaults may be useful — especially when the vaults have been deployed or upgraded recently — to ensure that all the system parameters have been set correctly. 

We chose property-based tests — written in Foundry and ready to be run by its fuzzer — in order to make the properties executable (and thus testable). In the future, they may also be run by symbolic execution or model checking tools to formally verify that the given vault satisfies the properties for all possible inputs and conditions.

We wrote the properties to be general enough to be applied to a wide range of vaults that implement different business logic. We used only public interface functions to make them agnostic to implementation details. (Due to this restriction, however, certain standard requirements that refer to implementation-specific internal data were omitted from the properties.)

For example, the following property corresponds to one of the requirements of the convertToShares() function, “MUST NOT show any variations depending on the caller.” Given the two account addresses and the amount, it makes each of the accounts call convertToShares() with the same amount, and ensures the two return values are equal. This property is independent of the implementation details of convertToShares(), which varies across vaults and must be satisfied by any vaults that implement ERC4626. This property can be executed by providing specific input values (for unit testing), many random inputs (for fuzz testing), or symbolic values (for symbolic execution and formal verification). It can also be run locally or against a mainnet fork (for integration testing).

Use case: properties that test for rounding errors

Rounding errors, for example, are an important class of (seemingly minor) bugs that can have some series implications. The underlying accounting logic of ERC4626, e.g., calculating the number of shares to be minted, or the amount of assets to be withdrawn, is implemented using fixed-point arithmetic — rounding errors are inevitable. For biztonság, however, the standard explicitly specifies the preferred rounding direction for each interface function, while leaving the error bounds unspecified and implementation-dependent. Specifically, the deposit() és a redeem() functions should return an alatt-approximation of the exact value, while the mint() és a withdraw() functions should return an felett-approximation. For example, if the current share price (i.e., the amount of assets per share) is 2, then deposit() with 3 wei of assets should only mint up to 1 wei of shares (i.e., floor(3/2)), míg withdraw() with 3 wei of assets should burn at least 2 wei of shares (i.e., ceil(3/2)).

We wrote the rounding-related properties to be independent of the underlying accounting logic by treating it as a black box. Specifically, we formulated them as so-called “round-trip” properties, which describe the relationship between two opposite functions. For example, the following property specifies that withdrawing assets that have just been escrowed by minting N shares must burn no less than N shares. In other words, no one can make a free profit converting assets and vault shares back and forth by repeatedly minting and withdrawing.

snippet from ERC4626 property tests

Indeed, we found that several ERC4626 vaults on mainnet fail to satisfy the above property due to rounding errors. This means that anyone could earn, for example, a couple of satoshi BTC (1 satoshi ~= 0.02 cent at the time of writing) by simply (and repeatedly) minting and withdrawing, slowly draining the vault. This may actually turn a profit on chains that enjoy very low gas fees (e.g., Fantom), or if the asset price becomes high enough in the future.

Testing the ERC4626 standard in the wild

We tested our properties against ~100 ERC4626 vaults on mainnet, and found many vaults that failed to follow the standard requirements — mostly due to the rounding errors (e.g., using floor rounding where ceiling is desired, as we described). Specifically, certain vaults failed to mint the exact number of shares requested by the mint() function, although the standard explicitly requires ezt. Some of them also emitted an inconsistent Deposit event where the logged data is different from what was actually minted. To our surprise, some vaults never minted on the spot at all; instead, they just put the mint requests into a queue, and process them later in a batch as a separate transaction.

Although these divergent behaviors were not exploitable per se, they may become vulnerable when integrated into other systems that expect only the standard behaviors. These issues will make vault integration much harder, potentially neutralizing the ongoing efforts and driving motivation behind standardization.

Using our property tests, and other actionable steps toward standard conformance

Following the standard precisely can prevent divergent behaviors (ideally before they’re ever deployed). We hope our properties help, along with a few additional action items. For those who are developing and/or integrating ERC4626 vaults:

  • We highly recommend running our property tesztek against your vaults. They will quickly find issues if there are any clear violations of the standard.
  • We also suggest reviewing our ingatlanait to cross check your understanding of the standard requirements, and adjust your implementation if there is any unintentional discrepancy.
  • If your vault has to diverge from the standard, we recommend clearly documenting the non-standard behaviors, so that others can properly handle these deviations when integrating with your vault. Please note that this should be considered as a last resort.

***
ERC4626 vaults have the potential to become an important building block for DeFi in the foreseeable future — and, for the sake of  composability, it’s important for both new and existing vaults to follow the standard. New implementations will emerge following the standard, so there’s no better time than the present to standardize existing vaults. 

As we work toward an ideal state (where different vaults are uniformly composable), ERC4626 property tests can be run to more easily detect standard violations in vault implementations. The property tests (with documentation and examples) are all publicly available in our Github raktár. We welcome your feedback and contributions!

***
Az itt kifejtett nézetek az AH Capital Management, LLC („a16z”) egyes alkalmazottainak nézetei, és nem az a16z vagy leányvállalatai nézetei. Az itt található bizonyos információk harmadik féltől származnak, többek között az a16z által kezelt alapok portfólióvállalataitól. Noha megbízhatónak vélt forrásokból származnak, az a16z nem ellenőrizte önállóan ezeket az információkat, és nem tesz kijelentést az információk aktuális vagy tartós pontosságáról, illetve annak egy adott helyzetre való megfelelőségéről. Ezenkívül ez a tartalom harmadik féltől származó hirdetéseket is tartalmazhat; az a16z nem vizsgálta át az ilyen hirdetéseket, és nem támogatja az abban található reklámtartalmat.

Ez a tartalom csak tájékoztatási célokat szolgál, és nem támaszkodhat rá jogi, üzleti, befektetési vagy adótanácsadásként. Ezekkel a kérdésekkel kapcsolatban konzultáljon saját tanácsadójával. Bármely értékpapírra vagy digitális eszközre történő hivatkozások csak illusztrációs célt szolgálnak, és nem minősülnek befektetési ajánlásnak vagy ajánlatnak befektetési tanácsadási szolgáltatások nyújtására. Ezen túlmenően ez a tartalom nem befektetőknek vagy leendő befektetőknek szól, és nem is szánható felhasználásra, és semmilyen körülmények között nem támaszkodhat rá az a16z által kezelt alapokba történő befektetésről szóló döntés meghozatalakor. (A16z alapba történő befektetésre vonatkozó ajánlatot csak az ilyen alap zártkörű kibocsátási memoranduma, jegyzési szerződése és egyéb vonatkozó dokumentációja tesz, és azokat teljes egészében el kell olvasni.) Minden említett, hivatkozott befektetés vagy portfóliótársaság, ill. A leírtak nem reprezentatívak az a16z által kezelt járművekbe történő összes befektetésre, és nem garantálható, hogy a befektetések nyereségesek lesznek, vagy a jövőben végrehajtott egyéb beruházások hasonló tulajdonságokkal vagy eredménnyel járnak. Az Andreessen Horowitz által kezelt alapok befektetéseinek listája (kivéve azokat a befektetéseket, amelyek esetében a kibocsátó nem adott engedélyt az a16z számára a nyilvánosságra hozatalra, valamint a nyilvánosan forgalmazott digitális eszközökbe történő be nem jelentett befektetéseket) a https://a16z.com/investments oldalon érhető el. /.

A benne található diagramok és grafikonok kizárólag tájékoztató jellegűek, és nem szabad rájuk hagyatkozni befektetési döntések meghozatalakor. A múltbeli teljesítmény nem jelzi a jövőbeli eredményeket. A tartalom csak a feltüntetett dátum szerint beszél. Az ezekben az anyagokban megfogalmazott előrejelzések, becslések, előrejelzések, célok, kilátások és/vagy vélemények előzetes értesítés nélkül változhatnak, és eltérhetnek mások véleményétől, vagy ellentétesek lehetnek azokkal. További fontos információkért látogasson el a https://a16z.com/disclosures oldalra

Időbélyeg:

Még több Andreessen Horowitz