Separate ERC-20 deposit and queued withdrawal whitelists
Description
The tokenInfos
mapping is defined as a storage variable in Liquifier:
mapping(address => TokenInfo) public tokenInfos;
This mapping is keyed by ERC-20--token contract addresses and stores information about the particular token; TokenInfo
is defined in ILiquifier:
struct TokenInfo {
IStrategy strategy;
uint128 strategyShare;
uint128 ethAmountPendingForWithdrawals;
bool isWhitelisted;
}
The boolean isWhitelisted
is used both for the whitelist of tokens that depositWithERC20WithPermit
can directly accept and for the whitelist of tokens that queued deposits made through depositWithQueuedWithdrawal
can contain.
Impact
In the future, Gadze Finance SEZC may want to whitelist tokens for depositWithERC20
that are not whitelisted by EigenLayer yet. Doing this would be awkward, since the strategy field of the TokenInfo
struct must either be null or not null. If it is not null, then a false strategy must be deployed to satisfy the underlyingToken()
call matching the token. If it is null (which can be achieved by calling updateWhitelistedToken
without calling registerToken
), then getTotalPooledEther
and getTotalPooledEtherSplits
for the token will revert because it expects to be able to call into info.strategy.sharesToUnderlyingView
.
Also, in the future, EigenLayer could whitelist new strategies for existing tokens without considering the impact on Gadze Finance SEZC. This impact could be large if Gadze Finance SEZC whitelisted a token for direct deposits without considering the risk associated with the way EigenLayer's whitelisted strategy slashes withdrawals, and it is not possible to consider this risk because the former whitelisting could happen before the latter strategy is even created.
Recommendations
With the remediation for Finding ref in mind, we recommend completely separating the whitelist for queued deposits through EigenLayer (which should be a strategy whitelist, according to that finding, instead of a token whitelist that maps to one strategy per token) and the whitelist for directly depositing ERC-20s, which should still be a token whitelist.
Additionally, consider the amount of logic that needs to be added if another token is whitelisted. The curve pools and the getTotalPooledEther
function already hardcode Lido, cbETH, and wbETH. If an upgrade to the contract is likely to support more ERC-20s, then a dynamic storage whitelist is unnecessary — the whitelist can just be expressed in the code of the contract, which costs much less gas for the user.
Remediation
This finding was made irrelevant by the design choice to only whitelist one strategy per token in the remediation for Finding ref.