The StrategyArb
, StrategyMainnet
, and StrategyOp
contracts inherit from BaseStrategy
and are designed to integrate with the TokenizedStrategy
to create fully ERC4626-compliant vaults. However, the strategies fail to implement the availableWithdrawLimit
and availableDepositLimit
correctly to have EIP4626-compliant
maxMint
, maxDeposit
, maxWithdraw
and maxRedeem
. leading to incompatibility with EIP4626 standards. This issue can result in unexpected Denial-of-Service (DoS) for other users and contracts.
According to the code comment and documentation, the entire vault should be fully ERC4626 compliant.
A Strategy contract can become a fully ERC-4626 compliant vault by inheriting the
BaseStrategy
contract, that uses the fallback function to delegateCall the previously deployed version ofTokenizedStrategy
.
A strategist only needs to override a few simple functions that are focused entirely on the strategy specific needs to easily and cheaply deploy their own permissionless 4626 compliant vault.
However, the strategy
fails to correctly implement vault-related limits, for example availableWithdrawLimit
, leading to incompatibility with EIP4626 standards.
TL&DR: The availableWithdrawLimit
function only considers available funds (asset.balanceOf(address(this))
and unexchanged balances from the transmuter
). It fails to account for conditions where the transmuter.withdraw
function becomes unusable due to the strategy
being unwhitelisted
or the transmuter
being disabled
.
Detailed explanation:
Let's take the maxWithdraw
function for example(this is also the case for maxDeposit
, maxMint
and maxRedeem
).
In EIP4626, to be compliant.
the
maxWithdraw
MUST return the maximum amount of assets that could be transferred fromowner
throughwithdraw
and not cause a revert, which MUST NOT be higher than the actual maximum that would be accepted
Let's take a dive into the maxWithdraw
function.
In TokenizedStrategy
, it's calling _maxWithdraw
which will call IBaseStrategy(address(this)).availableWithdrawLimit
.
For example, in StrategyArb
, the availableWithdrawLimit
is defined as below:
However, when we look at the vault's _withdraw
function, when the active assets are not enough, the freeFunds
is called, which will eventually call transmuter.withdraw
.
But in the Transmuter::withdraw
, the function requires the strategy
to be whitelisted
, as defined in the Whitelist contract. If the strategy is unwhitelisted, withdrawals fail, leading to a revert.
There are several cases when isWhitelisted
return false
according to whitelist.sol: either the transmuter
is disabled
or the strategy
is later unwhitelisted
by the admin.
However, this case is not considered by the availableWithdrawLimit
: when isWhitelisted
returns false, the vault can not withdraw
ALETH
from the transmuter
, thus the entire transaction will revert.
Per EIP4626
, the maxWithdraw
function must return the maximum amount of assets that can be withdrawn without causing a revert. The current implementation does not meet this requirement, as it fails to consider cases where transmuter.withdraw
is inaccessible. This violates the EIP4626
standard as we said before. When others are interacting with the TokenizedStrategy
, they could suffer from unexpected DoS.
The implementation of Strategy
violates the EIP4626
standard, and is not fully compatible as claimed. Users interacting with the strategy
may experience unexpected DoS when withdrawal attempts fail due to unconsidered scenarios.
Manual Review, EIP4626 Documentation
It is recommended to take these cases into account for the strategy to be fully compatible.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.