Root Cause
TrustedVolumes' custom Request-for-Quote (RFQ) swap proxy contract exposed a signer-registration function with no access control modifier. Any external account could call the function, self-register as an allowed signer, then submit fraudulent swap orders that the contract accepted as legitimate — because signature recovery returned an address on the allowlist.
// Pseudocode illustrating the vulnerable allowlist function
contract RFQSwapProxy {
mapping(address => bool) public allowedSigners;
// BUG: No onlyOwner, no role check, no gate whatsoever
function addSigner(address signer) external {
allowedSigners[signer] = true;
}
function executeOrder(
Order calldata order,
bytes calldata sig
) external {
address recovered = ECDSA.recover(orderHash(order), sig);
require(allowedSigners[recovered], "Unauthorized signer");
// Transfers assets to order.recipient — controlled by attacker
_settle(order);
}
}
The fix is trivial — add onlyOwner or an AccessControl role guard to addSigner. The absence of this guard turned the entire protocol's asset custody into an open withdrawal function.
Attack Steps
| Step | Detail |
|---|---|
| 1 | Attacker calls addSigner(attackerEOA) — no revert, no authorization check |
| 2 | Attacker signs fraudulent Order structs directing all major token balances to attacker wallets |
| 3 | Attacker calls executeOrder() — signature check passes (recovered address is now "allowed") |
| 4 | ~$6.7M in WETH, WBTC, USDT, USDC transferred out across multiple transactions |
| 5 | Stolen tokens swapped for ETH on DEX; proceeds split across three attacker-controlled addresses |
Attribution note (unconfirmed): Verichains' behavioral analysis of on-chain patterns suggests the same threat actor was responsible for the March 2025 1inch Fusion V1 exploit, bringing total attributed losses from this actor across two separate RFQ-architecture attacks to over $11M.
Impact
- Total drained: ~$6,700,000 (WETH, WBTC, USDT, USDC)
- Protocol: TrustedVolumes — Ethereum mainnet (1inch ecosystem liquidity provider/market maker)
- 1inch itself: Unaffected; 1inch clarified TrustedVolumes operates as an independent provider
- Recovery: Stolen assets converted to ETH and distributed across multiple wallets; no recovery reported
Lessons for Auditors
- Every external function that modifies a privilege set needs an access-control check. Functions that update allowlists, operator sets, or role mappings (
addSigner,addOperator,setAdmin) must be gated byonlyOwner, anAccessControlrole, a multi-sig, or time-locked governance. This is non-negotiable. - Enumerate all external/public write functions. RFQ, order-matching, and signature-scheme contracts often have auxiliary admin functions that auditors overlook. Systematically list every
externalandpublicnon-view function and verify authorization for each. - Recurring attacker specialization. Linking the same behavioral fingerprint to the 2025 Fusion V1 exploit suggests a threat actor who specifically hunts RFQ and signature-scheme weaknesses. Protocols in this architecture class should pay extra attention to order-authorization paths.
- Prefer immutable signer sets where possible. If the authorized signer set rarely changes, consider making it immutable at deployment or requiring a governance vote to update — eliminating the attack surface entirely.