TrustedVolumes Exploit Analysis
On May 7, 2026, TrustedVolumes, an independent DeFi liquidity provider and RFQ market maker, was exploited, resulting in a loss of approximately $6.7M on-chain.
Protocol Overview
TrustedVolumes operates as a market maker and resolver in DeFi, specializing in Request-for-Quote (RFQ) systems. Rather than relying on AMM pools, it quotes prices for token pairs and fulfills signed orders directly from its own inventory. It served as a liquidity resolver for aggregators including 1inch Fusion, providing deep liquidity for WETH, WBTC, USDT, and USDC.
The protocol’s core mechanism is a custom RFQ proxy contract. Makers pre-authorize signers, takers submit signed orders to the proxy, and the proxy verifies signatures before executing atomic token swaps via transferFrom from the maker’s approved inventory.
Background
Contracts
RFQProxy(0xeEeEEe53033F7227d488ae83a27Bc9A9D5051756): The public entry point. Routes calls viaDELEGATECALLto the implementation.RFQImplementation(0x88eb28009351Fb414A5746F5d8CA91cdc02760d8): Contains the order-filling logic. Unverified on Etherscan.InventoryVault(0x9bA0CF1588E1DFA905eC948F7FE5104dD40EDa31): Holds TrustedVolumes’ token reserves with unlimited ERC-20 approvals granted to the proxy.
Key Functions
registerAllowedOrderSigner(address signer, bool allowed): Registers an EOA as an authorized signer for orders wheremsg.senderis the receiver. Intended to be called only by the maker.fill-order function (selector
0x4112e1c2): Verifies the order signature, checks replay protection, then executes the token swap by pulling fromorder.inventoryinto the recipient address.
Normal Order-Fill Flow
TrustedVolumes registers its authorized signers via
registerAllowedOrderSigner.A taker requests a quote; TrustedVolumes’ authorized signer signs an order specifying the token pair, amounts,
inventorysource, and a unique salt.Taker submits the signed order to fill-order.
The proxy recovers the signer via
ecrecoverand checksallowedOrderSigner[order.receiver][signer].Replay protection confirms the salt has not been used.
Proxy pulls tokens from
order.inventoryto the recipient and receives payment in return.Order is marked as filled.
Key Information
Attacker EOA: 0xC3EBDdEa4f69df717a8f5c89e7cF20C1c0389100
Exploit contract: 0xD4D5DB5EC65272B26F756712247281515F211E95
Attack transaction: 0xc5c61b3ac39d854773b9dc34bd0cdbc8b5bbf75f18551802a0b5881fcb990513
Exploit Analysis
Intended vs. Actual Behavior
Normally, registerAllowedOrderSigner should only be callable by the maker, binding a trusted signer to that maker’s receiver address. The fill-order function should then verify that the signer is authorized for the same receiver whose inventory is being pulled. These two checks - signer authorization and token source - were expected to be tightly coupled.
They were not.
The Attack
After looking at the end of the attack transaction, the attacker ended up with 1,291 WETH, 206,282 USDT, 16.939 WBTC, and 1,268,771 USDC - all drained from TrustedVolumes’ vault in a single atomic transaction. How was this possible?
Step 1 - Deploy and register. The attacker deployed exploit contract 0xD4D5DB5EC65272B26F756712247281515F211E95. In its constructor, it immediately called registerAllowedOrderSigner(attacker_EOA, true). Because the function had no access control whatsoever, this succeeded - the attacker’s EOA was now a valid signer for any order where the exploit contract was the receiver.
Step 2 - Approve a nominal amount. The exploit contract approved 4 wei of USDC to the RFQ proxy. This was enough to pass any basic sanity check on the taker-payment side of the fill.
Step 3 - Forge four fills. Back to the attack transaction: the attacker called fill-order four times in a single tx, once per token (WETH, USDT, WBTC, USDC). Each order was crafted with:
inventoryset to TrustedVolumes’ vault (0x9bA0CF1588E1DFA905eC948F7FE5104dD40EDa31).receiverset to the exploit contract.Signed by the attacker’s registered EOA.
The authorization check - allowedOrderSigner[order.receiver][signer] - passed, because the signer was registered for the exploit contract as receiver. But the transferFrom pulled tokens from order.inventory, which was TrustedVolumes’ vault. The check and the token source referred to completely different addresses.
Normally, filling the same order twice would fail on replay protection. But the implementation read the fill status from one storage key and wrote it to a different key. The order was never actually marked as filled. All four drains - WETH, USDT, WBTC, USDC - executed without issue.
Step 4 - Exfiltrate. The exploit contract forwarded all stolen assets to the attacker’s EOA. Each fill sent 1 wei USDC back to TrustedVolumes as nominal “payment.”
The entire operation completed in one Ethereum block.
Conclusion
Permissionless signer registration:
registerAllowedOrderSignerhad no access control, allowing any address to register an arbitrary EOA as a valid signer for itself as receiver.Authorization/source mismatch in fill-order: The signer validity check used
order.receiveras the authorization scope, while the token pull usedorder.inventoryas the source. These two fields were independently attacker-controlled, breaking the assumed coupling between “who authorized the order” and “whose funds are being moved.”Broken replay protection: The order fill-status check read from a different storage slot than the write, meaning no order was ever durably marked as filled. The same forged order could execute multiple times within a single transaction.
Unlimited approvals on inventory: The vault held unlimited ERC-20 approvals to the proxy for all major assets. While a common market-maker pattern for speed, it maximized the blast radius once the above bugs were exploited.
The combination of these flaws meant that any external actor could drain the entire inventory vault in a single transaction with no prior permissions or capital. Restricting registerAllowedOrderSigner to the maker alone, and binding the authorization check to the same address as the token source, would each independently have prevented the exploit. The absence of public audits and unverified contract bytecode made external detection impossible before the attack.



