TLDR: ERC-4626 is a standard for tokenized vaults.
Before the introduction of ERC-4626, every vault had its own distinctive specification and implementation details. This made integration difficult, error prone, and wasteful.
ERC-4626 attempts to solve this problem by introducing a standard specification to lower integration efforts and create more consistent and robust implementation patterns, just like ERC-20.
What Is ERC-4626?
ERC-4626 is a standard↗ that improves the technical parameters of yield-bearing vaults.↗ It provides a standard API for tokenized yield-bearing vaults that represent shares of a single underlying ERC-20 token.
Tokenized vaults have become an extremely common pattern across DeFi. Yield aggregators, lending markets, staking derivatives, and many more dApps utilize and rely on tokenized vaults. Examples of tokenized vaults include Yearn and Balancer. As a yield aggregator, Yearn↗ vaults enable users to deposit digital assets and receive yield. Balancer, an automated portfolio manager and liquidity provider, relies on vaults at the core of its business logic. These vaults manage tokens in various pools. At the same time, they separate the token accounting and management from the pool logic.
Protocols tokenize their vaults to enhance liquidity and flexibility. Tokenized vaults allow for easy trading and utilization of assets across DeFi platforms. Additionally, they enable the creation of diverse, interconnected financial products. The industry has continually advocated for this paradigm, often referred to as “Money Legos”.
However, composability without proper adaptability or standardization creates challenges. It not only makes it difficult for developers to conform to industry standards like ERC-20 but also confuses new developers. Without proper adaptability or standardization, it is difficult to review new changes and verify the implementation details of an integration.
ERC-4626 has been proposed↗ to solve this problem and simplify integration while allowing DeFi players to eventually adopt a more secure and robust unified specification for vaults. This will also in turn reduce the attack surfaces protocols need to cover while integrating tokens across multiple protocols.
What Security Issues Does ERC-4626 Prevent?
By providing a uniform standard for projects to follow, ERC-4626 speeds up the building of cross-protocol integrations. A familiar, uniform standard is also easier for developers to reason about, which makes coding mistakes less likely. This helps prevent composability issues. Standardization also prevents duplication of work, since the community only needs to design the vaults once, rather than individually for every protocol. And since that design work is often error prone, it helps avoid repeating well-established yet common design pitfalls.
We will go over two case studies here to showcase what sort of issues ERC-4626 can prevent.
Rari Capital Incident
Rari Capital was hacked↗ for approximately $11 million worth of tokens, which amounted to 60% of all users’ funds in the Rari Capital Ethereum Pool.
In summary, Rari Capital was hacked due to an insecure cross-protocol
implementation. Its Ethereum Pool deposited ETH into Alpha Finance’s
ibETH token contract as a yield-generating strategy. This specific
strategy tracked the value of its ibETH/ETH
rate through the
ibETH.totalETH() / ibETH.totalSupply()
formula. This can have an
incorrect output in a scenario such as that in this attack, for example
while invoking the ibETH.work()
function, as debt value can get
artificially inflated.
The attacker simply called the deposit()
and withdraw()
functions in
the
RariFundManager↗
contract repeatedly, draining the Rari Fund Manager. The deposit()
and
withdraw()
functions would need to get the balance of the pool in
order to calculate the number of REPT tokens to be issued to the caller
or the amount of ETH to be issued to the caller, respectively. This
operation, in turn, would invoke the getBalance()
function from the
Alpha pool, calling the ibETH contract and its totalETH()
function↗.
Rari was unaware of the possibility of manipulating this function.
There is another function in the ibETH contract: ibETH.work()
. This
function can call any contract specified by the user. This makes it
possible for the deposit()
and withdraw()
functions from Rari to
become reentrant and called multiple times.
The work()
function is a payable
function, meaning that users can
control the amount of ETH in the ibETH contract through the work()
function, thereby changing the value returned by the totalETH()
function. Even worse, the work()
function also supports calling any
other contracts such as RariFundManager.
Through this function, the attacker can again send ETH and inflate the
totalETH
amount in the ibETH contract and, in return, redeem more
assets while invoking withdraw
from the RariFundManager contract.
The excerpt below from the postmortem speaks very clearly about the importance of the ERC-4626 proposal, in terms of adopting more unified specifications for integrations in order to avoid attack scenarios such as this.
*To avoid issues like this in the future, we will be implementing the following additional security measures:
- Enlist the protocols we integrate to review our integrations of them for security. This is by far the most important security measure, as the protocols themselves know the code they wrote better than anyone else.*
The incident underscores the critical risks of inadequate integration and incompatible designs in DeFi contracts. It highlights how a standard like ERC-4626, promoting uniform behavior and mutual understanding, could prevent such attacks by adding an essential layer of security and predictability.
Cream Finance Incident
Cream Finance was exploited↗ in a sophisticated attack that took advantage of two fundamental weaknesses in the platform, a manipulatable hybrid oracle and an uncapped supply of tokens. The critical component of the attack was the manipulation of the hybrid oracle, which influenced the perceived value of the yUSD tokens. This was achieved when the attacker sent a substantial amount of Yearn 4-Curve tokens to the yUSD vault, altering the exchange rate that the vault reported and, consequently, the oracle’s perceived value of the yUSD tokens.
The key lesson here is the importance of a robust and nonmanipulable price oracle for the stability of DeFi protocols. Time-weighted average price (TWAP) oracles, which calculate average prices over a specific period, could have helped prevent this hack as they’re more resilient to sudden price manipulation. This unfortunate event underscores the crucial role of secure and reliable oracles in ensuring the health and robustness of DeFi ecosystems.
With ERC-4626, protocols are now encouraged to implement
the convert
method as using a time-weighted average price in
converting between assets and shares.
These, alongside other vulnerable patterns, can be accounted for and mitigated with the help of careful adoption and implementation of ERC-4626.
Potential Security Pitfalls Under ERC-4626
There are always tradeoffs. With tokenized vaults, it is important to take caution for potential pitfalls when integrating them into smart contracts.
Managing feeOnTransfer
Tokens
If the vault is intended to support feeOnTransfer
tokens, check that
the amounts and shares in the vault are in their expected ranges,
respectively, when a fee is subtracted upon a transfer of assets.
Proper Use of decimals
Although the convertTo
functions should eliminate the need for any use
of an EIP-4626 vault’s decimals
variable, it is still strongly
recommended to mirror the underlying token’s decimals
whenever
feasible. This practice helps eliminate potential sources of confusion
and simplifies integration across various front ends and for off-chain
users.
Rounding
According to the spec↗, Vault implementers should be aware of the need for specific, opposing rounding directions across the different mutable and view methods, as it is considered most secure to favor the vault itself during calculations over its users:
- If (1) it’s calculating how many shares to issue to a user for a certain amount of the underlying tokens they provide or (2) it’s determining the amount of the underlying tokens to transfer to them for returning a certain amount of shares, it should round down.
- If (1) it’s calculating the amount of shares a user has to supply to receive a given amount of the underlying tokens or (2) it’s calculating the amount of underlying tokens a user has to provide to receive a certain amount of shares, it should round up.
The only functions where the preferred rounding direction would be
ambiguous are the convertTo
functions. To ensure consistency across
all EIP-4626 vault implementations, it is specified that these functions
MUST both always round down. Integrators may wish to mimic rounding up
versions of these functions themselves, for example by adding one Wei to
the result.
What You Give Is Not (Necessarily) What You Get
The amount of underlying assets a user may receive through redeeming
their shares in the vault (previewRedeem
) can be significantly
different than the amount that would be taken from them when minting the
same quantity of shares (previewMint
). The differences may be small
(e.g., if due to rounding error) or significant (e.g., if a vault
implements withdrawal or deposit fees). Therefore, integrators should
take care to use the preview function most relevant to their use case
and never assume they are interchangeable.
Overriding Core Functionality
To implement or extend intended functionalities, utilizing existing hooks is the suggested approach rather than altering core functions. This practice ensures a more manageable trace for effective code testing and auditing.
The Zero Share Case
The original spec for ERC-4626 has not↗ outlined how to handle the edge cases in which there are zero numbers of shares available in a vault and whether the vault should work as normal or revert. This can turn into a potential source of confusion and error.
Vaults as Price Oracles
With regards to the risk of oracle price manipulation attacks,
the preview
methods return values that are as close as possible to
exact as possible. For that reason, they are manipulatable by altering
the on-chain conditions and are not always safe to be used as price
oracles. The 4626 spec includes convert
methods and a totalAssets
method that are allowed to be inexact and therefore can be implemented
as robust price oracles. For example, it would be correct to implement
the convert
methods using a time-weighted average price in converting
between assets and shares.
Implementation-Specific Issues
An integrator must review any implementation of a tokenized vault before further integration, as potentially malicious implementations available out there can look like conforming to the interface while consisting of completely different design specifications in their core functions.
EOA Direct Access
If a vault is meant to be directly accessed through EOAs, its implementation needs to have functions available to accommodate slippage loss or unexpected deposit/withdraw limits. Unlike smart contracts, EOAs have no fail-safe mechanism for transaction reversion if the exact output is not achieved while invoking the four core functions.
Vault Extensions
As more actors start to adopt ERC-4626 standard, we will get to see more extensions implemented for the standard. For instance, Superform has developed an experimental MultiVault extension↗ to support multiple assets with separate accounting within one vault contract. Naturally, the more an implementation deviates from the original standard, the higher the likelihood of introducing new vulnerabilities. Developers and auditors can find their very own optimum based on their use case in terms of how much deviation is actually worth the risk.
It is important to note that it is not minimal additions per protocol that will lead to catastrophic events but the sum of them while integrated together.
The potential attack vectors mentioned above are some of the more discussed issues surrounding the 4626 standard. As the rate of adoption increases, we will definitely get to explore more angles of implementations of and integrations with 4626 vaults.
Additional Reading
- ERC-4626: Tokenized Vaults↗
- ERC-4626 Resources↗
- ERC4626 Property Tests (a16z↗, Trail of Bits↗)