The allocateFunds
function in Treasury.sol
allows allocators to assign arbitrary amounts to recipients without checking if the treasury holds sufficient funds. This creates a discrepancy between allocated amounts and actual balances, leading to invalid accounting.
function allocateFunds(address recipient,uint256 amount) external override onlyRole(ALLOCATOR_ROLE) {if (recipient == address(0)) revert InvalidRecipient();if (amount == 0) revert InvalidAmount();_allocations[msg.sender][recipient] = amount;emit FundsAllocated(recipient, amount);}
The allocateFunds function takes a recipient and an amount but doesn't specify a token. The contract tracks a totalValue and balances per token, but allocations aren't tied to any specific token. It only tracks a generic amount
and increments _totalValue
, which aggregates all token balances. So the problem here is that when an allocator calls allocateFunds, they can allocate any amount without considering which tokens are available.
For example,
Treasury holds 100 RAAC and 200 USDC (total value = 300).
An allocator can "allocate" 300 RAAC (even though only 100 RAAC exists).
The allocation succeeds because _totalValue
(300) ≥ allocated amount (300), but the actual RAAC balance is insufficient.
The contract allows this because it only checks the totalValue across all tokens, not individual token balances. This means allocations are based on the total value, not actual token availability.
POC
Allocation Succeeds Incorrectly: The test exposes the critical flaw where allocations are allowed to exceed actual token balances.
Withdrawal Fails Correctly: The withdrawal properly reverts due to insufficient funds, but this is only because the treasury lacks a validation mechanism during allocation.
Impact Demonstrated: The test proves that the treasury’s accounting is broken, as it permits allocations that cannot be fulfilled.
If off-chain systems or users see an allocation, they might assume the Treasury has the specific tokens to back it up. But when they try to withdraw, the transaction fails because the actual token balance is insufficient. This can lead to confusion, failed transactions, and loss of trust in the protocol.
Modify allocateFunds
to track allocations per token and validate balances:
2.Adjust mappings to track allocations per token:
3. Ensure withdrawals reference token-specific allocations:
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.