#41689 [SC-Insight] Blacklisting a Kodiak vault unintentionally whitelists a previously blacklisted token
Submitted on Mar 17th 2025 at 15:32:22 UTC by @peppef for Audit Comp | Yeet
- Report ID: #41689
- Report Type: Smart Contract
- Report severity: Insight
- Target: https://github.com/immunefi-team/audit-comp-yeet/blob/main/src/contracts/Zapper.sol
- Impacts:
- Contract fails to deliver promised returns, but doesn't lose value
Description
In the Zapper.sol contract the methods updateSwappableTokens() and updateWhitelistedKodiakVault() helps the blacklisting token and vault processes.
```solidity
function updateSwappableTokens(address token, bool isWhitelisted) external override onlyOwner {
_updateWhitelistedTokens(token, isWhitelisted);
}
function _updateWhitelistedTokens(address token, bool isWhitelisted) private {
require(token != address(0), "Zapper: token is zero address");
whitelistedTokens[token] = isWhitelisted;
emit TokenWhitelisted(token, isWhitelisted);
}
function updateWhitelistedKodiakVault(address vault, bool isEnabled) external override onlyOwner {
... // other code
whitelistedKodiakVaults[vault] = isEnabled;
... // other code
if (!whitelistedTokens[token0]) {
_updateWhitelistedTokens(token0, true);
}
if (!whitelistedTokens[token1]) {
_updateWhitelistedTokens(token1, true);
}
}
```
However they both edit the state of the mapping _updateWhitelistedTokens[] which can lead to a weird scenario where blacklisting a vault which involves a blacklisted token has the contrary effect to whitelist it again in _updateWhitelistedTokens[].
Proof of Concept
Suppose the following scenario:
-
A token named $BAD_TOKEN is blacklisted by the owner using the following code
updateSwappableTokens(bad_token_address, false)This, through
_updateWhitelistedTokens()private function setswhitelistedTokens[bad_token_address] = false -
At this point zapIn and zapOut methods are still usable on vaults involving $BAD_TOKEN since the
onlyWhitelistedKodiakVaults()modifier only checks for whitelisted vaults in the mappingwhitelistedKodiakVaults[] -
For this reason the owner proceeds to blacklist the first vault involving $BAD_TOKEN, for example
wBERA/BAD_TOKENvault withupdateWhitelistedKodiakVault(wBera_BadToken_vault, false)This function call sets
whitelistedKodiakVaults[wBera_BadToken_vault] = falsebut at the same time whitelists again bad_token_address insidewhitelistedTokens[]which was previously blacklisted due to the howupdateWhitelistedKodiakVault()is implemented -
Additionally the owner needs some time to blacklist all the other vaults involving $BAD_TOKEN for example: HONEY/BAD_TOKEN, USDT/BAD_TOKEN, USDC/BAD_TOKEN and thus, in the meanwhile, those vaults are still being usable by users and every potential blacklisting call to
updateSwappableTokens()is useless due to nextupdateWhitelistedKodiakVault()call.