Reflex engaged Guardian to review the security of their protocol. From March 26 through April 6, 2026, a team of 2 auditors reviewed the source code and recorded the findings in this report.
- Published
- Rounds
- Main Review, Remediation Review
- Language
- Solidity
- Chains
- Ethereum, BNB Chain, Arbitrum, Base, Hyperliquid
- Sector
- Infrastructure
- 0 Critical
- 4 High
- 2 Medium
- 5 Low
- 12 Informational
Scope
Overview
Reflex engaged Guardian to review the security of their protocol. From March 26 through April 6, 2026, a team of 2 auditors reviewed the source code and recorded the findings in this report.
Findings 23
Main Review
19 findings-
H-01 High Unvalidated Fallback Enables Profit Theft Access Control Resolved
Description
The
ExecutionRouterfallback can transfer tokens tomsg.senderduring theLOAN_CALLBACK_TYPE_ONGOINGphase based entirely on caller-controlled calldata, without validating that the caller is the expected pool. This is dangerous because the router can temporarily hold intermediate route tokens while a swap is in progress. If external execution is reachable during that callback window, an attacker can trigger the fallback, pull those tokens, complete the arbitrage independently, and return enough value for the router’s own flow to finish with zero profit. The loan still repays, but Reflex captures nothing and the attacker keeps the MEV.Recommendation
Validate
msg.senderagainst the expected callback pool before honoring theLOAN_CALLBACK_TYPE_ONGOINGbranch. Store the expected callback sender when the swap starts and reject any other caller.Resolution
Reflex: Acknowledged; mitigated off-chain by the Reflex team.
-
H-02 High Missing Access Control On V4/Pancake Callbacks Access Control Resolved
Description
unlockCallbackandlockAcquiredcheck the router’s callback state, but do not verify thatmsg.senderis the expected PoolManager or Pancake vault. During the callback window, any contract that can re-enter can reach these handlers. If a malicious caller reaches the V4/Pancake ongoing-swap path, the router can be induced to settle real tokens to the attacker-controlled contract while treating the fake caller as the swap context. The attacker can then extract the arbitrage profit, return enough assets for the router flow to finish, and leave Reflex with zero captured revenue.Recommendation
Validate callback callers against the tracked in-lock context or an equivalent expected-caller mapping, and reject any callback that does not come from the legitimate PoolManager or vault.
Resolution
Reflex: Acknowledged; mitigated off-chain by the Reflex team.
-
H-03 High Missing Output Meta Causes Profit Loss Logical Error Resolved
Description
Standalone V4 and Pancake lock/unlock payloads only carry one token metadata value. The callback then reuses that same metadata as both input and output token info. When a standalone V4 or Pancake hop outputs native ETH, the router decides whether to wrap based on the wrong token. Instead of wrapping the actual output token, it uses the input token metadata. That can make the route revert during output handling, and in after-swap integrations the revert is swallowed, so the user swap lands but Reflex captures no profit.
Recommendation
Carry
tokenMetaOutthrough every standalone V4 and Pancake lock/unlock payload and callback instead of reusingtokenMetaInfor output handling.Resolution
Reflex: Resolved.
-
H-04 High Unfunded Swap Path Leaks Arbitrage Profit Logical Error Resolved
Description
The router explicitly pre-funds the next V2-like hop after a V2/V3 loan, but it does not do the same when a V4 or Pancake hop is followed by a V2-like hop. V4 and Pancake outputs stay on the router, and the next V2-like pair is called without receiving its input tokens first. That makes the next V2-like swap revert. In after-swap integrations the revert is swallowed, so the triggering user swap still lands but Reflex captures nothing. The leftover arbitrage can then be taken by an external searcher.
Recommendation
Centralize the fix in
_swapFlow()and pre-fund a V2-like hop whenever the previous hop was V4 or Pancake.Resolution
Reflex: Resolved.
-
M-01 Medium Wrong Profit Token When Initial Hop Is Non-zero Logical Error Acknowledged
Description
triggerBackrunalways extracts the profit token fromtokenMeta[0], even though the route can start at anyinitialHopIndex. When the initial hop is not zero, the router snapshots the wrong token balance, computes profit against the wrong asset, and distributes nothing. The real profit remains stranded in the contract until an admin withdraws it manually.Recommendation
Use
initialHopIndexwhen extracting the profit token so profit accounting follows the actual route entrypoint.Resolution
Reflex: Acknowledged.
-
M-02 Medium tx.origin Used As Profit Recipient In Hooks Unexpected Behavior Acknowledged
Description
The hook contracts use
tx.originas the backrun profit recipient and LP-share fallback. That works for simple EOA flows, but breaks for smart wallets, relayers, and account-abstraction setups. In those cases, profits can be misdirected to the bundler, relayer, or submitting signer instead of the intended user or calling contract.Recommendation
Do not use
tx.originto determine the payout recipient. Pass the intended beneficiary explicitly through the execution flow.Resolution
Reflex: Acknowledged.
-
L-01 Low Native ETH Routes Revert In triggerBackrun DoS Acknowledged
Description
V4 and Pancake hop execution supports native ETH, but
triggerBackrunalways treats the profit token as an ERC20. If the route starts with native ETH, the router attempts ERC20 balance accounting againstaddress(0)and reverts. This means otherwise valid native-ETH-only routes can fail entirely at profit accounting time.Recommendation
Add explicit native ETH handling to
triggerBackrunwhen the profit token isaddress(0).Resolution
Reflex: Acknowledged.
-
L-02 Low V4/Pancake Hops Settle Fixed amountIn DoS Acknowledged
Description
The V4 and Pancake full-swap paths settle debt using the quoted
amountInrather than the actual swap input delta. On partial fills, the real debt can be smaller than the quoted amount. That causes the router to over-settle, leaving an unclaimed credit in the pool manager or vault. The leftover delta can then cause the transaction to revert at unlock finalization.Recommendation
Settle using the actual
deltaInreturned by the swap rather than the original quoted input amount.Resolution
Reflex: Acknowledged.
-
L-03 Low Fee-On-Transfer Token Burns Not Validated Validation Acknowledged
Description
The
burnfield intokenMetais unused everywhere in the router: All FOT handling is completely dependent on the quoter's pre-adjusted amounts. The router never checks that actual received amounts match expected amounts after burns. Loan repayment transfers a fixed pre-computed amount: The pool receives less thanvalid[initialHopIndex]after the burn fee is deducted, which can then fail pool invariant checks, causing a revert. The quoter must predict exactly which transfer path the router takes per hop to compute correct amounts.Recommendation
Use the burn field to adjust transfer amounts, or implement balance-based accounting rather than relying on pre-computed amounts for FOT tokens.
Resolution
Reflex: Acknowledged.
-
L-04 Low Silent Uint112 Truncation Of amountIn Validation Acknowledged
Description
In
ReflexAfterSwap::_reflexAfterSwap,amountInis cast from uint256 to uint112 without validation: IfamountInexceedstype(uint112).max(~5.19e33), the value silently truncates, passing an incorrect amount to the quoter. The quoter computes a route based on the wrong amount, resulting in either no profit found or a suboptimal arbitrage. Due to the try-catch, the MEV opportunity is silently missed. While overflow is unlikely for standard 18-decimal tokens, it becomes realistic, for example, for non-standard high-decimal tokens.Recommendation
Add an overflow check before the cast:
Resolution
Reflex: Acknowledged.
-
I-01 Informational Unvalidated Zero Address Recipient Traps Funds Validation Resolved
Description
In
triggerBackrun, the recipient parameter is passed directly to_splitERC20asvariedRecipientwithout any zero-address check: WhenvariedRecipientis address(0), the varied share distribution block in_splitERC20is skipped entirely: With the default config allocating 80% to main recipients and 20% to the varied recipient, passingaddress(0)silently leaves 20% of profit plus undistributed in the contract. The admin can recover viawithdrawToken, but there is no indication to the caller that funds were partially retained.Recommendation
Validate recipient is non-zero in
triggerBackrun:Resolution
Reflex: Resolved.
-
I-02 Informational Unused _splitETH Function Superfluous Code Resolved
Description
ConfigurableRevenueDistributor::_splitETHis implemented but never called anywhere in the protocol.ReflexRouter::triggerBackrunuses_splitERC20for profit distribution, and no other code path invokes_splitETH. Note that if it were ever integrated for native ETH profit distribution, it also introduces reentrancy risk viarecipient.call{value: share}("").Recommendation
Remove
_splitETHif native ETH distribution is not intended. If it is planned for future use, ensure to add reentrancy protection.Resolution
Reflex: Resolved.
-
I-03 Informational withdrawEth Uses Fixed 2300 Gas Compatibility Resolved
Description
withdrawEthuses.transfer()which forwards only 2300 gas to the recipient: This may fail if_tois a contract that requires more than 2300 gas to receive ETH.Recommendation
Use a low-level call instead:
Resolution
Reflex: Resolved.
-
I-04 Informational Missing Event In updateDefaultConfig Events Resolved
Description
ConfigurableRevenueDistributor::updateSharesemitsSharesUpdatedafter modifying a configuration, butupdateDefaultConfigdoes not: Off-chain indexers and systems trackingSharesUpdatedevents will not detect changes to it from the default configuration.Recommendation
Emit
SharesUpdatedinupdateDefaultConfig.Resolution
Reflex: Resolved.
-
I-05 Informational Fee Discount Requires Dynamic Fee Configuration Documentation Resolved
Description
In both
UniswapV4HookandPancakeSwapInfinityHook,beforeSwapreturnsLPFeeLibrary.OVERRIDE_FEE_FLAGto grant the router zero fees on backrun swaps: This override is only in effect if the pool was initialized with dynamic fees enabled in its pool key. If the pool uses static fees, the flag is silently ignored and the router pays the full LP fee on every backrun, reducing captured MEV profit for users.Recommendation
Document that pools integrating Reflex hooks must be initialized with dynamic fees enabled for the fee discount to function. Consider adding a validation check during pool initialization to ensure compatibility.
Resolution
Reflex: Resolved.
-
I-06 Informational Immutable Owner In Hook Contracts Configuration Resolved
Description
In both
UniswapV4HookandPancakeSwapInfinityHook,owneris declared immutable. If the owner key needs to be rotated for security reasons or operational changes, the existing hook's admin functions (router updates, config changes, fee discounts) cannot be transferred to a the new owner.Recommendation
Implement a
transferOwnershipfunction with a two-step transfer pattern to allow safe owner rotation.Resolution
Reflex: Resolved.
-
I-07 Informational External Function Has Internal Naming Convention Best Practices Resolved
Description
_donateToPoolin bothUniswapV4HookandPancakeSwapInfinityHookis declared external but uses an underscore prefix, which by Solidity convention indicates internal or private visibility: The function is external to enable try-catch on self-calls, however, the underscore prefix is misleading and may cause confusion during future development.Recommendation
Rename to
donateToPoolto reflect its external visibility.Resolution
Reflex: Resolved.
-
I-08 Informational Hooks Can Siphon MEV Via Return Delta Warning Acknowledged
Description
The router executes arbitrage routes through any V4 or PancakeSwap pool the quoter selects, however, V4 and PancakeSwap hooks can modify swap return deltas through
beforeSwap/afterSwap(including adjusting deltas, taking fees, or making external calls). A hook on an intermediate pool in a route could reduce the swap output, effectively siphoning a portion of the expected arbitrage profit. The router does not validate actual swap output against expected amounts, so reduced output from a hook goes undetected as long as the remaining amount is sufficient to complete the route and repay the loan.Recommendation
Document the trust assumptions around routing through UniswapV4 and PancakeSwap pools, while ensuring the quoter only routes through pools with verified and trusted hooks.
Resolution
Reflex: Acknowledged.
-
I-09 Informational Loan For V2 Without Callback Silently Skipped Informational Resolved
Description
_triggerSwapRoutehas no branch handlingisUniswapV2WithoutCallbackas the initial hop. V2 without callback pools cannot execute the initial hop since they lack thedataparameter needed for flash swaps. If the quoter selects one, the function silently does nothing (no swap executes, profit = 0, and gas is wasted).Recommendation
Ensure the quoter does not return
isUniswapV2WithoutCallbackas the initial hop, or add an explicit check/revert to fail gracefully rather than silently revert if this occurs.Resolution
Reflex: Resolved.
Remediation Review
4 findings-
L-01 Low Backrun Failure Return Value Is Ambiguous Unexpected Behavior Acknowledged
Description
In
BackrunEnabledSwapProxy::swapWithBackrun, the dev comments state that failed backruns are identified by zero return values: However,triggerBackrunreturns(0, address(0))on a successful execution when no arbitrage opportunity exists: This makes a successful, although unprofitable, backrun execution identical to a caught revert/failure. This will affect callers attempting to distinguish between a route with no arbitrage available and a broken route that consistently fails, preventing appropriate retry and error handling.Recommendation
Consider handling the case where a successful
triggerBackruncall returns (0, address(0)) as success rather than unexpected failure.Resolution
Reflex: Acknowledged.
-
I-01 Informational Admin Changes Can Silently Skip MEV Capture Trust Assumptions Acknowledged
Description
If the admin calls
setReflexRouteror modifies fee discounts viasetGlobalFeeDiscount/setPoolFeeDiscountwhile a user's swap transaction is pending, the backrun may silently fail. The previous router loses its fee discount, causing the backrun to pay full LP fees, which can eliminate the arbitrage profit. The try-catch in_reflexAfterSwapskips the failure, and the user's swap completes normally but without receiving any MEV redistribution.Recommendation
Consider documenting that admin operations on hook contracts should be performed during low-activity periods to minimize impact on pending user swap
Resolution
Reflex: Acknowledged.
-
I-02 Informational Native ETH Donate Fails In Hook Contracts Informational Acknowledged
Description
In
donateToPoolwithin bothUniswapV4HookandPancakeSwapInfinityHook, the WETH/ETH branch only matches when currency is native ETH and profitToken is WETH: If bothcurrencyandprofitTokenareaddress(0)(native ETH), the first branch is skipped sinceprofitToken != weth, and the else branch callsIERC20(address(0))::safeTransferwhich reverts. Currently, sponsors have confirmed that profit token is not expected to be native ETH. However, if this changes in the future, the current hook contracts are incompatible and will cause unexpected reverts.Recommendation
Consider adding handling for the case where both profitToken and currency are native ETH, or document that if ETH is added as a profit token in the future, the UniswapV4 and PancakeSwap hook contracts are incompatible.
Resolution
Reflex: Acknowledged.
-
I-03 Informational Redundant Add Operation In _bytesToAddress Superfluous Code Resolved
Description
_bytesToAddresscontains a redundantaddoperation in its assembly block.add(add(d, 20), 0)is functionally identical toadd(d, 20), wasting an opcode.Recommendation
Simplify to
addr := mload(add(d, 20)).Resolution
Reflex: Resolved.
No findings match.
Put your code through the same review.
This review started with a conversation about scope. Tell us what you are building and we will plan yours with you.
