KiloEx TrustedForwarder Unauthenticated Price Update / Leveraged Drain (2025-04-14)

  • Name: KiloEx TrustedForwarder unauthenticated price update / leveraged drain
  • Date: 2025-04-14
  • Protocol: KiloEx
  • Chain: Base, opBNB, BNB Chain, Taiko, and Manta Pacific
  • Category: oracle write-path authentication failure / trusted-forwarder access control bug / self-published false price / leveraged vault drain
  • Loss: about $7.4M-$7.5M across chains; public reporting later said the funds were returned after negotiations
  • Summary: KiloEx did not lose funds because an external market or third-party oracle was manipulated. It lost funds because its own price-update trust chain could be impersonated through a user-facing forwarder. Public analyses and KiloEx’s own post-mortem described a trust chain where KiloPriceFeed trusted Keeper, Keeper trusted PositionKeeper, and PositionKeeper trusted TrustedForwarder / MinimalForwarder. The attacker used the inherited execute() entrypoint on that forwarder with a crafted meta-transaction request accepted as if it came from an authorized source; the downstream delegateExecutePositions path only checked msg.sender == trustedForwarder and did not re-verify that the real initiator was an approved keeper. That let the attacker push KiloEx’s internal ETH price down to about $100, open leveraged longs, then push the same internal price up to about $10,000 and close the positions for profit. The same flaw was reused across KiloEx deployments on Base, opBNB, BNB Chain, Taiko, and Manta.
  • Trigger / entry point:
    • KiloEx exposed a meta-transaction path through a TrustedForwarder contract derived from OpenZeppelin-style MinimalForwarderUpgradeable logic.
    • Public incident analyses and KiloEx’s post-mortem say that this forwarder inherited OpenZeppelin’s MinimalForwarderUpgradeable execute() without overriding it into a permissioned path, so an attacker-crafted request could enter the downstream keeper chain as if it were authorized.
    • That mattered because KiloEx’s price-setting flow relied on chained trust rather than one isolated signer check: KiloPriceFeed -> Keeper -> PositionKeeper -> TrustedForwarder.
    • Once the attacker could enter that chain as if they were an approved sender, they could publish arbitrary internal prices through the protocol’s own keeper path.
  • Root cause:
    • The decisive failure was not ordinary oracle manipulation and not a bad external price feed.
    • The decisive failure was authentication collapse on KiloEx’s own oracle write path: a user-facing forwarder sat upstream of privileged keeper logic and accepted a crafted request that should never have been treated as oracle authority.
    • KiloEx therefore published its own false ETH price as protocol truth, and its leveraged trading vault paid out against that fiction.
    • The preserved lesson is that meta-transaction forwarders, relayers, and keeper-call chains belong inside the oracle security boundary if they can reach price-setting code.
  • Exploit path:
    1. The attacker funded address 0x00fac92881556a90fdb19eae9f23640b95b4bcbd from Tornado Cash in Ethereum tx 0xa0fa4ab8ded0c07085d244e1981919b440f78b609e1cf8d7f8ee32d358dfdf46 on 2025-04-13.
    2. On 2025-04-14, the attacker called execute() on KiloEx’s TrustedForwarder with a crafted request and signature accepted by the meta-tx path.
    3. That forged call propagated through PositionKeeper / Keeper into the protocol’s price-setting flow and let the attacker set KiloEx’s internal ETH price to about $100.
    4. With ETH marked absurdly low inside KiloEx, the attacker opened leveraged ETH long positions against the protocol vault.
    5. The attacker then used the same privileged path to push KiloEx’s internal ETH price to about $10,000.
    6. KiloEx’s own position accounting treated the manipulated internal mark as real PnL, so the attacker closed positions for large profits and withdrew vault assets.
    7. The attacker repeated the same pattern across multiple KiloEx deployments, including Base, opBNB, BNB Chain, Taiko, and Manta, draining about $7.4M-$7.5M in aggregate.
  • What the attacker needed to be true:
    • A user-reachable forwarder or relayer path had to be able to impersonate or satisfy the authority expected by the privileged price-update stack.
    • KiloEx had to honor its own internal keeper-published price as trading-settlement truth without an independent sanity bound that would reject an ETH move from roughly market levels to $100 or $10,000.
    • The vault design had to let trader PnL withdraw real liquidity from LPs once the internal mark moved.
    • The same broken authority pattern had to exist on more than one deployment, so the attacker could replay it chain by chain.
  • Technical anatomy worth remembering:
    • This is a strong contrast case for oracle-manipulation. The attacker did not need to move ETH spot markets, distort a TWAP venue, or corrupt an external oracle network. KiloEx printed the false price for them.
    • It also sits inside state-publication-authority-failure more than generic access control bug because the economic failure was that the protocol’s own oracle publication boundary was wired wrong. A valid-looking local price update path emitted fiction as settlement and PnL truth.
    • The keeper chain matters: no single contract looked like anyone can set price in isolation if reviewers only stared at the leaf. The exploitable surface emerged from chained trust assumptions across TrustedForwarder, PositionKeeper, Keeper, and KiloPriceFeed.
    • KiloEx is also a clean reminder that multi-chain expansion multiplies operational blast radius when the same privileged update path is cloned across deployments.
  • Representative transactions and addresses:
    • Tornado Cash funding tx: 0xa0fa4ab8ded0c07085d244e1981919b440f78b609e1cf8d7f8ee32d358dfdf46
    • Primary attacker address on Ethereum / Base / BNB Chain / opBNB / Taiko: 0x00fac92881556a90fdb19eae9f23640b95b4bcbd
    • Secondary attacker / forged from address cited by incident analyses: 0x551f3110f12c763d1611d5a63b5f015d1c1a954c
    • Manta-linked attacker address: 0xd43b395efad4877e94e06b980f4ed05367484bf3
    • Base exploit txs:
      • 0x6b378c84aa57097fb5845f285476e33d6832b8090d36d02fe0e1aed909228edd (about $3.12M)
      • 0xde7f5e78ea63cbdcd199f4b109db2a551b4462dec79e4dba37711f6c814b26e6
      • 0xf0fcce0807a82041d050a60461e187f0e81a6f7fbda69bb600c04049d924e138
    • BNB Chain exploit txs:
      • 0x1aaf5d1dc3cd07feb5530fbd6aa09d48b02cbd232f78a40c6ce8e12c55927d03 (about $893k)
      • 0x38b25be14b83fd549d5e0b29ba962db83d41f5f9072d0eac4f692fa8e7110bc0
    • opBNB exploit txs:
      • 0x79eb28ae21698733048e2dae9f9fe3d913396dc9d93a0e30d659df6065127964 (about $2.9M)
      • 0xcfc679a66f1d2966dbe83bb827409c40f29f881c20128107ae73e93ab55c65e4
      • 0x783d56ce53af6d59c7c4be374ff48a66257733fadf5905526b5862a54917889f
    • Taiko exploit tx: 0x9bce6e105cea138fe9fb1e4bfb63fe90d21817db9d2cc6d1bf7697317430215b
    • Manta exploit tx: 0x06074831103a1e91c7b6dcb3b641cf4b79bfa208ea75e99cf9b5100d60a82df5
  • Response / mitigation:
    • KiloEx suspended platform activity after the incident and publicly acknowledged the exploit.
    • The team coordinated with SlowMist, exchanges, bridge providers, and law enforcement, and publicly called for partner blacklisting of the attacker addresses.
    • KiloEx published an onchain / public negotiation offering a bounty for return of funds.
    • Public reporting later said the attacker returned the assets after several days and that KiloEx moved toward a recovery and compensation process.

Pattern tags

  • Write-path envelope authentication failure: a user-reachable meta-transaction forwarder plus chained keeper logic let attacker-authored calldata inherit oracle-publication authority.
  • Internal-price publication boundary failure: KiloEx did not merely consume a bad outside price; it published its own false ETH mark through the keeper path and treated that local mark as trading truth.
  • Same-window publish-and-settle collapse: the forged low ETH mark could open leveraged longs and the forged high ETH mark could close them for profit before any separate settlement skepticism or delayed publication boundary intervened.
  • Deployment-cloning blast radius: the same broken authority envelope existed across Base, opBNB, BNB Chain, Taiko, and Manta, so one trust-chain mistake became a multi-chain drain playbook.

Why the exploit worked

  • KiloEx put too much trust in the outer execution envelope. The downstream delegateExecutePositions path only cared that msg.sender was the approved forwarder, so the protocol effectively treated arrived through the trusted-forwarder shell as equivalent to originated from an authorized keeper.
  • That meant the real oracle root key was not one signer or one keeper address but the whole meta-tx envelope: TrustedForwarder request validation, sender reconstruction, keeper-chain propagation, and final price-publication call all had to stay one security object. They did not.
  • Once the forged call entered that chain, KiloEx had no independent bound forcing the published ETH mark to remain economically plausible before leveraged entry, PnL calculation, and vault withdrawal logic consumed it. A local write-path bug therefore became immediate reserve-paying truth.
  • The drain was a clean two-step publication / monetization loop rather than a fuzzy oracle got manipulated story: print ETH at about $100, enter oversized longs, print ETH at about $10,000, then close against the same protocol-authored fiction.
  • Multi-chain deployment amplified operational blast radius. Because the same privileged update path was cloned across several KiloEx instances, the attacker could replay one authority failure across five environments instead of fighting for one isolated payout.

Detection and audit pivots

  • Trace every privileged write path all the way back through relayers, meta-tx forwarders, and helper executors. Ask who actually authored this update? rather than stopping at the final msg.sender check on the leaf contract.
  • Re-verify authority after envelope translation. If a forwarder, router, or keeper-helper unwraps calldata on behalf of another actor, downstream privileged code should still prove the recovered initiator is the exact role allowed to publish price truth.
  • Separate keeper-authored local mark from mark safe to settle leveraged PnL against. If the protocol can publish an internal price quickly, it still needs an independent bound, delayed activation rule, or fail-closed degraded mode before vault inventory is released against that number.
  • Monitor for economically impossible local prints such as ETH moving from market levels to $100 or $10,000 inside one keeper update, and treat those as authority failures rather than just volatility alerts.
  • Audit cloned deployments as one shared trust surface. If the same forwarder / keeper / oracle stack is repeated across chains, one successful auth-bypass may imply instant replay risk everywhere else.

Why this incident matters

  • KiloEx is a compact, modern exemplar of a protocol publishing its own fake oracle truth through a broken authority chain rather than through market manipulation.
  • It preserves a useful meta-tx forwarder became oracle root key cousin inside the broader oracle-configuration family, which is analytically different from decimal mistakes, wrong-asset feed bindings, or fallback-overlay drift.
  • More sharply, KiloEx shows that execution envelope accepted as keeper-authentic and price safe to settle against were treated as the same claim. The missing control was not merely stricter role gating, but a healthier separation between who may publish a local mark, what exact envelope proves that publication is authentic, and when that mark may spend LP inventory.
  • It also shows that LP-backed perp systems have the same core failure mode as lending markets once a protocol-authored price becomes false: deeper-liquidity vault inventory is released against fiction immediately.
  • It is also a strong handoff into execution-envelope identity pinning, settlement envelope truth as a single security object, and internal-mark publication quarantine and reserve-spend separation. The healthy answer was not trust the forwarder harder; it was bind who authored the privileged update, bind what exact payload was authenticated, and keep freshly published internal marks from becoming instant reserve authority without an independent bound.

Internal linkages

Control surface

  • The decisive leverage sat in KiloEx’s TrustedForwarder, meta-transaction validation, recovered-sender semantics, keeper-call chain, and the absence of an independent sanity boundary between keeper-authored update and vault-settlement truth.
  • KiloEx did not mainly trust an external market incorrectly. It trusted its own local authority chain incorrectly, and then let that broken local truth settle leveraged PnL against real LP assets across several chains.
  • The healthier control object would have forced one coherent answer to three different questions: who authored this price update?, what exact payload did they authorize?, and is this freshly published local mark actually allowed to settle inventory right now?

What sound design looks like

  • A healthy perpetuals stack can name one exact authority object for every internal mark update: signer or keeper identity, signed payload hash, target market, nonce, expiry, forwarding path, and final price-write target all remain the same authenticated object from origin to leaf. Forwarder accepted the call is never allowed to stand in for the authorized price publisher approved this exact update.
  • Meta-transaction convenience and oracle authority are kept separate by default. If a forwarder must exist, privileged price-writing code still re-verifies the recovered initiator and signed payload fields at the leaf instead of inheriting trust from an upstream wrapper.
  • Published local marks and reserve-spending truth are different lifecycle states. Even a correctly authenticated keeper update should face market-specific plausibility bounds, movement caps, delayed activation, or a degraded-mode lane before leveraged entry, PnL realization, liquidation, or vault withdrawal can consume it.
  • Multi-chain replicas are treated as one operational trust surface. The protocol knows which deployments share the same forwarder / keeper / price-write assumptions, and it can revoke or quarantine that whole authority family faster than attackers can replay the same forged envelope chain by chain.
  • Monitoring is designed around valid-looking authority, impossible economics. A healthy system emits enough recovered-signer, payload-hash, market-id, and price-delta telemetry that responders can detect keeper path says yes, market says impossible before LP inventory is gone.
  • The clean design target is simple: one authenticated price-publication envelope, one narrow set of roles allowed to use it, one explicit separation between price observed and price safe to settle against, and one emergency kill path that can freeze the mark before it becomes vault-withdrawable truth.

Failure-prevention checklist

  • Treat the whole price-publication envelope as one security object: forwarder, signature verifier, recovered sender, keeper router, and price-writing leaf must all agree on the same authenticated origin.
  • Do not let msg.sender == trustedForwarder stand in for the recovered initiator is an authorized price publisher; privileged leaf functions should re-check the exact recovered role they mean to trust.
  • Bind authenticated payload fields tightly. The signer identity, market id, asset, price, nonce, expiry, and execution target should all be part of the verified envelope so an attacker cannot reuse a valid shell around a different economic action.
  • Keep public meta-tx convenience paths out of oracle-write surfaces unless the protocol can prove the forwarder is permissioned, domain-separated, replay-safe, and role-specific.
  • Separate price update accepted from price safe to settle leveraged positions against. Even authenticated keeper updates should face independent plausibility bounds, movement caps, or delayed activation before LP inventory is released.
  • Add hard sanity rails for high-value markets: if ETH jumps from roughly market levels to $100 or $10,000 inside one local update, the system should freeze settlement, degrade to shadow mode, or require stronger confirmation.
  • Replay audit fixes across every cloned deployment before resuming operations. If the same forwarder / keeper stack exists on five chains, patching one chain first is not a real containment strategy.
  • Log and monitor the recovered initiator, forwarder address, target function, signed payload hash, and resulting price delta for every privileged update so responders can spot valid envelope, impossible economics quickly.
  • Keep asset-local or market-local circuit breakers so one suspicious price-publication path does not immediately expose every LP vault and every chain replica.
  • Test forged-envelope scenarios directly in review: public caller -> trusted forwarder -> keeper helper -> price publish -> leveraged open/close -> vault withdrawal should be a standard adversarial bundle, not an afterthought.

Audit prompts

  • Which exact actor is allowed to publish price truth here, and how does the protocol prove that actor’s identity after every relay, forwarder, or helper hop?
  • Does any privileged leaf function rely on msg.sender being a trusted wrapper instead of verifying the recovered signer or role that actually authorized the economic action?
  • What exact fields are signed in the meta-transaction or keeper envelope, and could any economically meaningful field be swapped, replayed, or reinterpreted downstream?
  • Can a user-reachable forwarder call the same code path as a privileged keeper, even if the team thinks the forwarder is only a UX convenience layer?
  • If the protocol accepted an absurd local price print right now, what explicit mechanism would stop leveraged entry, PnL realization, and vault withdrawal before funds left the system?
  • Are cloned deployments using the same forwarder, keeper, and price-publication assumptions, and if one chain breaks, how quickly can the others be quarantined?
  • Does the protocol distinguish authenticated update arrived from economically safe mark to settle against, or are those treated as the same event?
  • What monitoring would fire on a forged-but-formally-valid keeper call: anomalous sender, anomalous payload, anomalous price move, or only the later drain?
  • Can responders disable one compromised publication envelope without disabling unrelated markets, chains, or operator paths?
  • If the recovered initiator, trusted wrapper, and economic payload ever disagree, which component fails closed first?

Lessons that should already be standard

  • Trusted forwarders belong inside the privilege boundary when they can reach oracle or settlement code.
  • Arrived through the approved wrapper is not the same claim as was authored by the approved signer.
  • Meta-transaction convenience layers become root keys the moment privileged code stops re-checking recovered identity downstream.
  • Authentication of the execution envelope and economic safety of the resulting price are separate controls; you need both.
  • A protocol publishing its own bad mark through a broken keeper path is still an oracle failure, even if no external market was manipulated.
  • Multi-chain replication multiplies authority failures; cloning the same keeper stack clones the same exploit.
  • Absurd local price moves should trigger settlement skepticism automatically, not only post-incident explanation.
  • Reviewers should audit forwarder -> helper -> privileged leaf as one path, because the exploit usually lives in the seams rather than in any one contract viewed alone.

Sources

Last reviewed

  • 2026-07-29 UTC