Contract fails to deliver promised returns, but doesn't lose value
Operators gain admin-equivalent allocation capabilities
Description
Summary
The allocate() function in AlchemistAllocator uses an inverted comparison operator (> instead of <) when applying the daoTarget cap for operators. This bug will grant operators the same allocation privileges as admins once daoTarget is properly implemented, bypassing intended governance restrictions.
Description
The AlchemistAllocator contract implements a privilege separation model where admins have unrestricted allocation rights, while operators should be subject to additional DAO-governed caps. The contract has two symmetric functions: allocate() and deallocate().
Wrong implementation in allocate(): https://github.com/alchemix-finance/v3-poc/blob/a192ab313c81ba3ab621d9ca1ee000110fbdd1e9/src/AlchemistAllocator.sol#L34C8-L40C10
Correct implementation in deallocate(): https://github.com/alchemix-finance/v3-poc/blob/a192ab313c81ba3ab621d9ca1ee000110fbdd1e9/src/AlchemistAllocator.sol#L56C7-L62C10
Key Differences
Function
Operator Check
Result
allocate()
adjusted > daoTarget ? adjusted : daoTarget
Takes maximum of both values (wrong)
deallocate()
adjusted < daoTarget ? adjusted : daoTarget
Takes minimum of both values (correc)
Current State vs Future Impact
Currently: The bug is dormant because daoTarget is hardcoded to type(uint256).max, making the check ineffective.
When implemented: Per the FIXME comment, daoTarget will be fetched from StrategyClassificationProxy. Once this happens, the inverted comparison will immediately allow operators to bypass governance-imposed caps.
Impact
Access Control Bypass
When daoTarget is properly implemented, operators will be able to allocate funds up to max(adjusted, daoTarget) instead of the intended min(adjusted, daoTarget), effectively granting them admin-level privileges.
Mitigation
Change the comparison operator in allocate() from > to <:
This change aligns allocate() with the correct logic already implemented in deallocate().
Proof of Concept
Proof of Concept
1.paste the following test in AllchemistAllocator.t.sol
2. run it via forge test --mt testInvertedComparisonBug -vvv