All incidents

ARA Swap Helper Approved-Holder Exploit

Share
Jun 18, 2023 16:37 UTCAttackLoss: 124,915.76 USDTPending manual check1 exploit txWindow: Atomic
Estimated Impact
124,915.76 USDT
Label
Attack
Exploit Tx
1
Addresses
2
Attack Window
Atomic
Jun 18, 2023 16:37 UTC → Jun 18, 2023 16:37 UTC

Exploit Transactions

TX 1BSC
0xd87cdecd5320301bf9a985cc17f6944e7e7c1fbb471c80076ef2d031cc3023b2
Jun 18, 2023 16:37 UTCExplorer

Victim Addresses

0x7ba5dd9bb357afa2231446198c75bac17cefcda9BSC
0xb817ef68d764f150b8d73a2ad7ce9269674538e0BSC

Loss Breakdown

124,915.76USDT

Similar Incidents

Root Cause Analysis

ARA Swap Helper Approved-Holder Exploit

1. Incident Overview TL;DR

On BNB Chain block 29214011, transaction 0xd87cdecd5320301bf9a985cc17f6944e7e7c1fbb471c80076ef2d031cc3023b2 used a flash-loan-funded attacker contract at 0x98e241bd3be918e0d927af81b430be00d86b04f9 to force passive holder 0xb817ef68d764f150b8d73a2ad7ce9269674538e0 through two swaps via helper 0x7ba5dd9bb357afa2231446198c75bac17cefcda9. The sequence drained the victim’s ARA into USDT, moved the Pancake V3 pool price with borrowed capital, forced the victim’s USDT back into ARA at manipulated terms, dumped attacker-held ARA back into USDT, repaid DODO pool 0x9ad32e3054268b849b84a8dbcc7c8f7c52e4e69a, and left 124915758354209141283962 USDT with attacker EOA 0xf84efa8a9f7e68855cf17eaac9c2f97a9d131366.

The root cause is a broken authorization boundary in 0x7ba5...::swapExactInputSingle(uint256,uint256,address,address). The helper spends tokens from a caller-supplied recipient address by calling transferFrom(recipient, ...) and then forwards the swap to Pancake V3 with that same recipient, but never verifies that recipient is msg.sender or otherwise authorized. Any unprivileged actor can therefore scan public approvals and trigger swaps against a passive holder whose balances and allowances are already present on-chain.

2. Key Background

The central protocol component is unverified helper contract 0x7ba5dd9bb357afa2231446198c75bac17cefcda9, which is wired to Pancake V3 router 0x13f4ea83d0bd40e75c8222255bc855a974568dd4, the ARA/USDT pool 0x92974438c330d5c6790b4260e358e84513109872, token0 USDT 0x55d398326f99059ff775485246999027b3197955, token1 ARA 0x5542958fa9bd89c96cb86d1a6cb7a3e644a3d46e, and fee tier 100. BscScan decodes the exposed entrypoint as swapExactInputSingle(uint256,uint256,address,address), and the seed trace confirms that the helper forwards into Pancake V3 exactInputSingle.

The passive holder at 0xb817ef68d764f150b8d73a2ad7ce9269674538e0 is not a contract. The auditor’s runtime-code check returns 0x, which means the address had no code at prestate and therefore could not have actively participated in the transaction:

0x

The seed prestate already contained everything the attacker needed: the victim had positive ARA and USDT balances plus approvals to both the helper and the router, and DODO pool 0x9ad3... held enough USDT to fund the attack. No victim transaction, signature, or private orderflow was required.

3. Vulnerability Analysis & Root Cause Summary

This is an ACT attack caused by a helper contract that treats an arbitrary external address as the token payer. The root-cause category is ATTACK, not MEV-only arbitrage, because the sequence relies on unauthorized third-party spending through the helper. The safety invariant should be: only the token owner or an explicitly authorized operator may initiate a swap that spends that owner’s ERC20 balance. Instead, the helper’s breakpoint is the transferFrom(recipient, address(this), amountIn) path inside swapExactInputSingle, where recipient comes directly from calldata and is not tied to msg.sender.

The seed trace shows that the helper first checks allowance(victim, helper) and allowance(victim, router), then pulls tokens from the victim, approves the router, and executes Pancake V3 with the victim still set as the recipient. That makes third-party approvals reusable by any arbitrary caller. Because the approvals and balances are public state, a searcher can discover victims off-chain, source temporary capital through a permissionless flash loan, and time the two forced victim swaps around attacker-controlled pool moves. The exploit is therefore deterministic from public prestate and does not depend on privileged attacker access. The violated principles are exactly the ones captured in the validated JSON: caller identity is not bound to token-spending authority, third-party approvals are treated as blanket execution permission, and untrusted callers are allowed to choose slippage-sensitive execution over third-party funds.

4. Detailed Root Cause Analysis

The trace excerpt below shows the exact unauthorized spending pattern in the seed transaction. The attacker-owned harness calls the helper with the passive holder as recipient, and the helper immediately spends the victim’s approved ARA before routing the output back to the victim:

0x98e241...::DPPFlashLoanCall(...)
  0x7BA5...::swapExactInputSingle(163497870920445229714611, 0, ARA, 0xB817...)
    ARA::allowance(0xB817..., 0x7BA5...)
    ARA::allowance(0xB817..., 0x13f4...)
    ARA::transferFrom(0xB817..., 0x7BA5..., 163497870920445229714611)
    0x13f4...::exactInputSingle((ARA, USDT, 100, 0xB817..., 163497870920445229714611, 0, 0))

Later in the same callback, after the attacker buys ARA with flash-loaned USDT, the same helper primitive is reused against the victim’s USDT balance:

0x7BA5...::swapExactInputSingle(132123869275720631745148, 0, USDT, 0xB817...)
  USDT::allowance(0xB817..., 0x7BA5...)
  USDT::allowance(0xB817..., 0x13f4...)
  USDT::transferFrom(0xB817..., 0x7BA5..., 132123869275720631745148)
  0x13f4...::exactInputSingle((USDT, ARA, 100, 0xB817..., 132123869275720631745148, 0, 0))

This behavior matches the decompiled helper analysis: allowance checks are keyed off the external recipient argument, transferFrom also uses that same recipient as payer, and there is no authorization check tying the payer to the caller. The attacker contract at 0x98e241... is only an execution harness around this primitive. Its role in the trace is to borrow 1202701257417339116619317 USDT from DODO, trigger the first victim swap, buy 504469005899784961117931 ARA from Pancake V3, trigger the second victim swap, sell the attacker-held ARA back to USDT, repay the flash loan, and forward remaining USDT to EOA 0xf84e....

The attack succeeds because three public conditions coexist at block 29214010: the passive holder still has spendable balances, the passive holder has already granted approvals to both the helper and the router, and the DODO flash-loan pool holds enough USDT to move the Pancake V3 price between the two forced victim swaps. Once those conditions exist, the exploit can be realized by any searcher using only public blockchain state. No separate non-monetary oracle is required here, because the success predicate is the direct USDT profit captured by the attacker.

5. Adversary Flow Analysis

The attacker cluster consists of EOA 0xf84efa8a9f7e68855cf17eaac9c2f97a9d131366 and contract 0x98e241bd3be918e0d927af81b430be00d86b04f9. The EOA sends the transaction and receives final profit. The contract performs the flash-loan callback sequence.

The on-chain flow is:

  1. 0xf84e... calls 0x98e241....
  2. 0x98e241... borrows 1202701257417339116619317 USDT from DODO pool 0x9ad3....
  3. Inside DPPFlashLoanCall, the attacker reads the victim’s full ARA balance and calls 0x7ba5...::swapExactInputSingle(..., ARA, victim), forcing the victim’s ARA into USDT.
  4. The attacker approves router 0x13f4... and swaps the borrowed USDT into ARA, pushing the ARA/USDT pool to a favorable state for the attacker’s second victim interaction.
  5. The attacker reads the victim’s resulting USDT balance and again calls 0x7ba5...::swapExactInputSingle(..., USDT, victim), forcing the victim’s USDT back into ARA at manipulated terms.
  6. The attacker sells its own ARA back into USDT, repays the DODO loan principal, and transfers the remaining USDT to 0xf84e....

The trace and balance diff show that the transaction is fully self-contained. There is no victim-originated transaction in the sequence, and there is no evidence of privileged keys, private contracts, or hidden permissions.

6. Impact & Losses

The measurable profit outcome is directly visible in the collector balance diff:

{
  "holder": "0xf84efa8a9f7e68855cf17eaac9c2f97a9d131366",
  "token": "0x55d398326f99059ff775485246999027b3197955",
  "before": "188168626369722195782",
  "after": "125103926980578863479744",
  "delta": "124915758354209141283962"
}

The same artifact shows a native-gas outflow of 1285740178653700000 wei for the attacker EOA, so the incident still leaves a strongly positive result after gas. The passive holder 0xb817... loses 8876933460457984207061 USDT net, while Pancake V3 pool 0x92974438c330d5c6790b4260e358e84513109872 loses 116038824893751157076901 USDT net. The total profit extracted by the attacker is 124915758354209141283962 USDT units, recorded as 18-decimal token units in the collected artifacts.

7. References

  • Seed transaction: 0xd87cdecd5320301bf9a985cc17f6944e7e7c1fbb471c80076ef2d031cc3023b2
  • Attacker EOA: 0xf84efa8a9f7e68855cf17eaac9c2f97a9d131366
  • Attacker harness: 0x98e241bd3be918e0d927af81b430be00d86b04f9
  • Vulnerable helper: 0x7ba5dd9bb357afa2231446198c75bac17cefcda9
  • Pancake V3 router: 0x13f4ea83d0bd40e75c8222255bc855a974568dd4
  • DODO flash-loan pool: 0x9ad32e3054268b849b84a8dbcc7c8f7c52e4e69a
  • ARA token: 0x5542958fa9bd89c96cb86d1a6cb7a3e644a3d46e
  • USDT token: 0x55d398326f99059ff775485246999027b3197955
  • Collector artifacts used: seed transaction trace, seed balance diff, and transaction metadata under /workspace/session/artifacts/collector/seed/56/0xd87cdecd5320301bf9a985cc17f6944e7e7c1fbb471c80076ef2d031cc3023b2/
  • Auditor artifacts used: helper disassembly /workspace/session/artifacts/auditor/iter_0/0x7ba5_swapExactInputSingle.disasm.txt and victim runtime-code check /workspace/session/artifacts/auditor/iter_1/victim_code.txt