56582 sc low alchemistcurator removestrategy is unable to remove strategies from vaults due to wrong logic implementation
Submitted on Oct 17th 2025 at 23:15:11 UTC by @hunter0xweb3 for Audit Comp | Alchemix V3
Report ID: #56582
Report Type: Smart Contract
Report severity: Low
Target: https://github.com/alchemix-finance/v3-poc/blob/immunefi_audit/src/AlchemistCurator.sol
Impacts:
Contract fails to deliver promised returns, but doesn't lose value
Description
Brief/Intro
AlchemistCurator::removeStrategy is unable to remove strategies from vaults due to wrong logic implementation. So, once a strategy is enabled in the vault there is no way to remove it by using AlchemistCurator contract
Vulnerability Details
First lets examine the process of adding an strategy adapter to a vault myt to see why removeStrategy logic flaw
Adding strategy is done with a two step process:
Call AlchemistCurator.sol::submitSetStrategy(adapter, myt)
Call AlchemistCurator.sol::setStrategy(adapter, myt)
These calls flow are for AlchemistCurator.sol::submitSetStrategy
We can see that inside _submitSetStrategy (called by submitSetStrategy) is a call to vault::submit
lib/vault-v2/src/VaultV2.sol::submit updates the timelock of the function signature of data variable declared in AlchemistCurator.sol::submitSetStrategy
If this timelock is not updated , the following call (AlchemistCurator.sol::setStrategy) will revert Now that timelock is updated a call to AlchemistCurator.sol::setStrategy(address adapter, address myt) is performed
Inside AlchemistCurator.sol::_setStrategy the adapter to myt address is updated and vault is called to add the adapter:
So, as it can be seen, the vault timelock has to be updated via vault.submit(data), with the planned data to call the vault (in this case addAdapter) before performing vault changes
The problem arises because AlchemistCurator.sol::removeStrategy doesnt update vault timelock to perform adapter removal because it doesnt call vault.submit method with vault.removeAdapter function data as argument and vault.submit is neither in the methods called inside AlchemistCurator.sol::removeStrategy
AlchemistCurator.sol::removeStrategy calls flow:
As it can be seen AlchemistCurator.sol::_setStrategy updates adapter to mty mapping and calls vault.removeAdapter
However because AlchemistCurator.sol::removeStrategy(adapter, myt) didnt call vault.submit(data) with data = calldata to remove the adapter then AlchemistCurator.sol::removeStrategy(adapter, myt) calls will always fail, leaving curators unable to remove strategies from vaults
Also note that no matter if adding or removing adapter to myt the mapping adapterToMyt is updated, and it should be clear when removing the adapter, because otherwise _vault(adapter) will return a vault even when the adapter was removed
Impact Details
Curators are unable to remove strategies from vaults due to AlchemistCurator::removeStrategy logic to remove adapter is wrongly implemented
Contract fails to deliver promised returns, but doesn't lose value
References
https://github.com/alchemix-finance/v3-poc/blob/a192ab313c81ba3ab621d9ca1ee000110fbdd1e9/src/AlchemistCurator.sol#L49-L53 https://github.com/alchemix-finance/v3-poc/blob/a192ab313c81ba3ab621d9ca1ee000110fbdd1e9/src/AlchemistCurator.sol#L62-L66 https://github.com/alchemix-finance/v3-poc/blob/a192ab313c81ba3ab621d9ca1ee000110fbdd1e9/lib/vault-v2/src/VaultV2.sol#L341-L348
Proof of Concept
Proof of Concept
The following PoC:
Shows that Vault's address for a non existent strategy is address(0) (expected)
Adds a new strategy to a vault and shows that adapterToMYT is updated (expected)
Tries to remove the previously added strategy but it will fail because AlchemistCurator::removeStrategy is wrongly implemented as described above
To perform the PoC add the following test case in src/test/AlchemistCurator.t.sol
Run test case , it will fail due to removeStrategy wrong logic
Implement modifications in both functions _setStrategy and removeStrategy in src/AlchemistCurator.sol
Run test case again, now function removeStrategy will work and adapter is removed from vault
Recomendation
Implemented a function AlchemistCurator::submitRemoveStrategy similar to submitSetStrategy that calls vault.submit or
Implement vault.submit(data) inside removeStrategy (as in the PoC above)
Was this helpful?