Reproduced Exploit
GlueX V2 — a partner is paid 0 while 1000 GLX of surplus stays in the router
swap turns the amount delivered above the quote into surplus, then pays the partner (surplus * partnerSurplusShare) / 10000. Nothing stops partnerSurplusShare from being 0. A swap that delivers 1000 GLX against a quote of 0 therefore computes a partner cut of 0, skips the partner transfer, and leav…
Chain
Other
Category
defi
Date
Jun 2025
Source
AuditVault
EVM Playground
Source-level debugger — step opcodes and Solidity in sync
The attack is replayed in an in-browser EVM preloaded with the exact dumped fork state. The execution tree shows every call; step by Solidity line or by opcode across all depths — source, Stack, Memory, Storage, Balances (native / ERC-20 / NFT), Transient storage and Return value stay in sync. Click a tree node, opcode, or source line to jump. No backend, no live RPC.
Source & credit. Reproduction of a public audit finding curated by AuditVault — the original finding: 61338-h-02-partner-can-receive-zero-share-despite-surplus-shieldif. Standalone Foundry PoC and full write-up: 61338-h-02-partner-can-receive-zero-share-despite-surplus-shieldif_exp in the
evm-hack-registrymirror.
Vulnerability classes: vuln/defi/fee-manipulation · vuln/logic/fee-calculation · vuln/logic/missing-check
Reproduction: a self-contained Foundry PoC that compiles and runs offline with only
forge-std— no fork and no RPC. Trace: output.txt. PoC: test/61338-h-02-partner-can-receive-zero-share-despite-surplus-shieldif_exp.sol.
Key info#
| Impact | HIGH — partner share is 0, the partner receives 0 GLX, and 1000 GLX of surplus stays in the router |
| Protocol | GlueX V2 GluexRouter |
| Vulnerable code | (surplus * desc.partnerSurplusShare) / 10000 with no floor |
| Bug class | A partner bps of 0 is accepted |
| Finding | Shieldify — GlueX V2, June 2025 · id 61338 / H-02 |
| Report | GlueX-V2-Security-Review.md |
| Source | AuditVault finding |
| Status | Acknowledged by GlueX. Reproduced here as a local synthetic. |
| Compiler | solc 0.8.27, cancun, via IR |
TL;DR#
swap turns the amount delivered above the quote into surplus, then pays the partner (surplus * partnerSurplusShare) / 10000. Nothing stops partnerSurplusShare from being 0. A swap that delivers 1000 GLX against a quote of 0 therefore computes a partner cut of 0, skips the partner transfer, and leaves the 1000 GLX sitting in the router. The partner's balance stays 0.
The fixed router treats a share below 10000 bps as 10000. The same zero-share call pays the partner 1000 GLX and the router balance ends at 0.
Vulnerable code#
From router_v1/GluexRouter.sol at the reviewed commit, lines 223-227:
if (surplus > 0 || slippage > 0) {
// @> VULN: partnerSurplusShare may be 0, so this product is 0 and the partner is skipped
uint256 partnerSurplus = (surplus * desc.partnerSurplusShare) / 10000;
uint256 partnerSlippage = (slippage * desc.partnerSlippageShare) / 10000;
uint256 partnerShare = partnerSurplus + partnerSlippage;
}
Shieldify asked for a floor:
+ require(desc.partnerSurplusShare >= MIN_SHARE && desc.partnerSlippageShare >= MIN_SHARE, "partner share too low");
This reduction uses that floor as a payment, not only a revert: a share of 0 is lifted to 10000 bps, so the partner receives the whole surplus.
Attack walkthrough#
- The caller mints 1000 GLX and approves the router.
swapis called withquoted = 0,delivered = 1000 GLX, and both partner shares set to 0.- The router pulls 1000 GLX.
surplus = 1000 GLX. partnerSurplus = (1000 * 0) / 10000 = 0.partnerSlippageis 0.partnerShareis 0.if (partnerShare > 0)is false, so the partner transfer does not run.- The partner's balance is 0. The router's balance is 1000 GLX.
Control: GluexRouterFixed on the same inputs sets the bps to 10000, transfers 1000 GLX to the partner, and leaves 0 in the router.
Diagrams#
Impact#
The partner who facilitated the route is paid 0 GLX. The 1000 GLX surplus remains in GluexRouter instead of being paid out. A caller can set the partner bps to 0 on every route and zero the partner's cut whenever surplus exists.
Remediation#
Reject a partner surplus or slippage share below the configured minimum before the product, which is what Shieldify recommended. Paying the partner requires the bps to be non-zero. In this reproduction the fixed router floors a 0 share to 10000 bps so the same call pays the partner the full surplus.
Sources#
- AuditVault finding 61338
- Shieldify GlueX V2 security review
- Reviewed router: gluex_router_contract@9c754a3
router_v1/GluexRouter.sol
Taxonomy#
severity/highvuln/defi/fee-manipulation·vuln/logic/fee-calculation·vuln/logic/missing-check
Sources & further analysis#
Reproductions & code
- Standalone PoC + full trace: 61338-h-02-partner-can-receive-zero-share-despite-surplus-shieldif_exp (evm-hack-registry mirror).
- AuditVault finding: 61338-h-02-partner-can-receive-zero-share-despite-surplus-shieldif.
Alerts & third-party analyses
These dashboards index community alerts tweets, post-mortems, and independent write-ups. Reach them through the protocol name above to cross-check this reproduction against other analyses.