Contract fails to deliver promised returns, but doesn't lose value
Description
Brief/Intro
Operator role in AlchemistAllocator.sol can allocate higher than DAO defined limits, potentially messing up internal accounting
Vulnerability Details
The AlchemistAllocator contract allows two users call AlchemistAllocator::allocate. Admin and operator. It also defines caps set by both the vault and DAO. Admins can deposit upto vault cap however operators are restricted to DAO defined caps. However, a wrong comparison logic allows operators bypass this check and deposit up to vault cap. Also, the adjusted variable, which tracks the cap, is never used for any check.
Impact Details
Operator addresses can allocate to vault, values above DAO defined limits. Potentially messing up internal accounting and allowing operators overexpose funds to risky strategies.
References
Recommended Mitigation: Cap adjusted for operator at DAO target and add check
Proof of Concept
Proof of Concept
Proof of Concept: Place the following inside MockAlchemistAllocator in AlchemistAllocator.t.sol to simulate allocate function with real DAO target
Place this in AlchemistAllocatorTest contract
This passes showing operators can deposit higher than dao limits
function testAllocateIgnoresDaoTargetCap() public {
_magicDepositToVault(address(vault), user1, 500 ether);
// Call with operator
vm.startPrank(operator);
bytes32 id = mytStrategy.adapterId();
// expected behavior: should cap at daoTarget (10 ether)
// current logic ignores this and allows 15 ether
allocator.allocateWithDaoCap(address(mytStrategy), 15 ether);
uint256 allocated = vault.allocation(id);
assertGt(allocated, 10 ether, "Allocation exceeded DAO cap");
vm.stopPrank();
}
Ran 1 test for src/test/AlchemistAllocator.t.sol:AlchemistAllocatorTest
[PASS] testAllocateIgnoresDaoTargetCap() (gas: 580424)
Suite result: ok. 1 passed; 0 failed; 0 skipped; finished in 14.81ms (2.99ms CPU time)
Ran 1 test suite in 171.49ms (14.81ms CPU time): 1 tests passed, 0 failed, 0 skipped (1 total tests)