Summary
The TODO
comment indicates missing logic to distribute RAAC tokens to managers, causing funds to be stuck.
function depositRAACFromPool(uint256 amount) external onlyLiquidityPool validAmount(amount) {
uint256 preBalance = raacToken.balanceOf(address(this));
raacToken.safeTransferFrom(msg.sender, address(this), amount);
uint256 postBalance = raacToken.balanceOf(address(this));
if (postBalance != preBalance + amount) revert InvalidTransfer();
emit RAACDepositedFromPool(msg.sender, amount);
Vulnerability Details
StabilityPool's depositRAACFromPool()
receives RAAC tokens but lacks distribution logic, causing rewards to be trapped in the contract instead of being allocated to managers according to their assigned weights.
Current State
Managers have allocated percentages (managerAllocation
mapping)
Total allocation tracked (totalAllocation
)
RAAC tokens transferable from liquidity pool
But missing Implementation Impact
function depositRAACFromPool(uint256 amount) external onlyLiquidityPool validAmount(amount) {
raacToken.safeTransferFrom(msg.sender, address(this), amount);
for (uint i = 0; i < managerList.length; i++) {
address manager = managerList[i];
uint256 managerShare = (amount * managerAllocation[manager]) / totalAllocation;
}
}
Resulting in a state where:
RAAC tokens accumulate in contract
Managers cannot access their allocated rewards
Incentive mechanism breaks down
Protocol participation decreases
The code accepts deposits without implementing the manager allocation logic, creating a direct path for tokens to become locked in the contract.
Parity Multisig Wallet incident where $280M worth of ETH became permanently locked due to incomplete contract logic. Both cases demonstrate how missing implementation of core functionality can lead to permanent asset lockup in smart contracts.
Impact
100% of deposited RAAC tokens become trapped
Manager incentives cease functioning
Maximum loss = Total RAAC deposits from liquidity pool
Tools Used
vs
Recommendations
Implement distribution based on managerAllocation
function depositRAACFromPool(uint256 amount) external onlyLiquidityPool validAmount(amount) {
uint256 preBalance = raacToken.balanceOf(address(this));
raacToken.safeTransferFrom(msg.sender, address(this), amount);
uint256 postBalance = raacToken.balanceOf(address(this));
if (postBalance != preBalance + amount) revert InvalidTransfer();
for (uint i = 0; i < managerList.length; i++) {
address manager = managerList[i];
uint256 managerShare = (amount * managerAllocation[manager]) / totalAllocation;
raacToken.safeTransfer(manager, managerShare);
emit ManagerRewardDistributed(manager, managerShare);
}
emit RAACDepositedFromPool(msg.sender, amount);
}