Summary
handleAgentTaxes() updates accounting state and records tax events before calling
_swapForAsset(), but it ignores the result of that external call.
Because _swapForAsset() returns a boolean success indicator, the current implementation can treat
failed swaps as if settlement succeeded.
Vulnerability details
function handleAgentTaxes( uint256 agentId, bytes32[] memory txhashes, uint256[] memory amounts, uint256 minOutput) public onlyRole(EXECUTOR_ROLE) { require(txhashes.length == amounts.length, "Unmatched inputs"); TaxAmounts storage agentAmounts = agentTaxAmounts[agentId]; uint256 totalAmount = 0; for (uint i = 0; i < txhashes.length; i++) { bytes32 txhash = txhashes[i]; if (taxHistory[txhash].agentId > 0) { revert TxHashExists(txhash); } taxHistory[txhash] = TaxHistory(agentId, amounts[i]); totalAmount += amounts[i]; emit TaxCollected(txhash, agentId, amounts[i]); } agentAmounts.amountCollected += totalAmount; _swapForAsset(agentId, minOutput, maxSwapThreshold);}Impact
The contract records tax processing in taxHistory and increases agentAmounts.amountCollected,
while agentAmounts.amountSwapped depends on the swap path succeeding. If the swap fails:
- tax events remain marked as processed
- accounting state advances
- the asset conversion may never happen
That creates a mismatch between recorded state and actual settlement.
Recommendation
Check the return value from _swapForAsset() and either revert on failure or route failed swaps
through an explicit retry or debt-accounting path. The state transition should not silently continue
when the settlement leg fails.