All incidents

OLY staking/router reward-abuse drains BEP20USDT from staking flows

Share
Jan 04, 2026 21:46 UTCAttackLoss: 179,644.56 USDTManually checked1 exploit txWindow: Atomic
Estimated Impact
179,644.56 USDT
Label
Attack
Exploit Tx
1
Addresses
4
Attack Window
Atomic
Jan 04, 2026 21:46 UTC → Jan 04, 2026 21:46 UTC

Exploit Transactions

TX 1BSC
0x827e23d6dc6bfdc06d6062f53203fd1ca6f3cc00f8bad21ea6bf9aa7d9b349ed
Jan 04, 2026 21:46 UTCExplorer

Victim Addresses

0x77190f0c8e97514c4fd3895fb5b4fb464961b46fBSC
0x46e185726084e8dc8a3ee8bd955e476237d49074BSC
0x55d398326f99059ff775485246999027b3197955BSC
0x544028231562a43b106fbceca722b65cb5c861b0BSC

Loss Breakdown

179,644.56USDT

Similar Incidents

Root Cause Analysis

OLY staking/router reward-abuse drains BEP20USDT from staking flows

BNB Chain (chainid 56) protocol OLY’s router, deployed as implementation contract 0x77190F0C8e97514c4fd3895FB5B4fb464961b46F behind TransparentUpgradeableProxy 0x46e185726084e8Dc8a3eE8bd955e476237d49074, exposes a function Unresolved_6f73978a that allows any caller to specify an arbitrary BEP20 token owner address and invoke BEP20USDT.transferFrom(owner, proxy, amount) using pre-existing approvals to the proxy. An unprivileged adversary EOA 0xf10395d26262b92cc95729f274965868bd7f938b deployed a helper contract 0x85616b87D4D5313D4Cb1f91370AE5A2297b3a2AB and, in a single transaction 0x827e23d6dc6bfdc06d6062f53203fd1ca6f3cc00f8bad21ea6bf9aa7d9b349ed at block 74081238, iterated over many USDT holders who had previously approved the proxy, draining their BEP20USDT balances via this arbitrary-from transferFrom path and routing proceeds into adversary-controlled aggregation addresses. The adversary cluster’s BEP20USDT holdings increased by 179644.562028178677753413 USDT, with victims collectively losing the same amount.

Key Background

The protocol is an OLY staking/router system on BNB Chain that integrates BEP20USDT (0x55d398326f99059ff775485246999027b3197955) and OLY (0x544028231562a43b106fbceca722b65cb5c861b0). User flows rely on a TransparentUpgradeableProxy at 0x46e185726084e8Dc8a3eE8bd955e476237d49074, which delegates calls to router implementation 0x77190F0C8e97514c4fd3895FB5B4fb464961b46F. Many EOAs had granted standard BEP20USDT approvals to the proxy, enabling it to move their USDT in normal staking or swapping operations.

The ACT pre-state σ_B is BNB Chain state at block 74081237, immediately before the adversary seed transaction at block 74081238. It consists of:

  • BEP20USDT balances and allowances for victim EOAs and the adversary-related cluster.
  • OLY token balances used in swap and staking flows.
  • Deployment and configuration of the proxy 0x46e18572… delegating to router implementation 0x7719…b46F.
  • Established BEP20USDT approvals from many EOAs to the proxy.

This pre-state is evidenced by:

  • Seed metadata for tx 0x827e23d6…:
// Seed metadata for 0x827e23d6… (BNB Chain, chainid 56)
{
  "chainid": 56,
  "txhash": "0x827e23d6dc6bfdc06d6062f53203fd1ca6f3cc00f8bad21ea6bf9aa7d9b349ed",
  "etherscan": {
    "tx": {
      "result": {
        "from": "0xf10395d26262b92cc95729f274965868bd7f938b",
        "hash": "0x827e23d6dc6bfdc06d6062f53203fd1ca6f3cc00f8bad21ea6bf9aa7d9b349ed",
        "to": null,
        "value": "0x0"
      }
    }
  }
}

(Source: seed metadata for tx 0x827e23d6…, artifacts under artifacts/root_cause/seed/56/0x827e23d6…/metadata.json.)

  • BEP20USDT and OLY verified source code:
    • BEP20USDT at 0x55d398326f99059ff775485246999027b3197955 (Contract.sol under artifacts/root_cause/seed/56/0x55d3983…/src/).
    • OLY at 0x544028231562a43b106fbceca722b65cb5c861b0 (OHM.sol under artifacts/root_cause/seed/56/0x5440282…/src/).
  • Router implementation decompile and ABI:
    • artifacts/root_cause/data_collector/iter_1/contract/56/0x77190F0C8e97514c4fd3895FB5B4fb464961b46F/decompile/….

The ACT opportunity uses a single adversary-crafted transaction sequence b consisting of one contract-creation transaction on chainid 56:

  • Transaction b[1]:
    • txhash: 0x827e23d6dc6bfdc06d6062f53203fd1ca6f3cc00f8bad21ea6bf9aa7d9b349ed
    • from: 0xf10395d26262b92cc95729f274965868bd7f938b
    • Type: standard BNB Chain contract-creation transaction with zero native value and sufficient gas.
    • Feasibility: sendable by any unprivileged EOA via public RPC/mempool; the calldata deploys a helper contract that, in the same transaction, drives arbitrary-from transferFrom calls through the established proxy/implementation.

No privileged roles, admin keys, or private orderflow are required to realize this strategy.

Vulnerability Analysis

The root cause is a design flaw in router implementation 0x7719…b46F behind TransparentUpgradeableProxy 0x46e18572…, specifically function selector 0x6f73978a (Unresolved_6f73978a in the decompile). This function accepts an owner address parameter and uses it directly as the from address in BEP20USDT.transferFrom, without constraining it to msg.sender or otherwise verifying ownership.

From the decompiled router code:

/// @custom:selector    0x6f73978a
/// @custom:signature   Unresolved_6f73978a(uint256 arg0, uint256 arg1, address arg2, address arg3, address arg4) public payable
function Unresolved_6f73978a(uint256 arg0, uint256 arg1, address arg2, address arg3, address arg4) public payable {
    // ...
    address var_d = address(arg2); // token address
    // ...
    address var_e = address(arg3); // owner address
    address var_g = address(this); // proxy / router context
    uint256 var_h = arg0;          // amount
    // ...
    (bool success, bytes memory ret0) = address(arg2).Unresolved_23b872dd(var_e); // call transferFrom
    // ...
}

(Source: heimdall decompile for router implementation 0x7719…b46F, 0x7719…-decompiled.sol.)

This decompile, combined with the ABI and traces, shows that:

  • arg2 is the BEP20 token address (BEP20USDT in the attack).
  • arg3 is the token-owner address used as the from parameter in transferFrom.
  • The function allows any caller to choose arg3 arbitrarily.

The BEP20USDT token at 0x55d3983… implements standard ERC-20 semantics, with transferFrom(owner, spender, amount) checking allowance[owner][spender] and balanceOf(owner) before moving tokens. Many users had previously approved proxy 0x46e18572… to spend their USDT.

A benign pre-incident transaction shows intended usage of this path by a regular user:

TransparentUpgradeableProxy::fallback(
  0x6f73978a...
  ... token = 0x55d398326f99059ff775485246999027b3197955 (BEP20USDT)
  ... owner = 0x939599136029208E46A1b79d485E12fec94c7056
  ... router/treasury = 0x13903A7E780ded720e2F35d5B8904d556a0552E0
)
  ├─ 0x7719…b46F::6f73978a(...) [delegatecall]
  │   ├─ PancakeFactory::getPair(USDT, OLY)
  │   ├─ BEP20USDT::transferFrom(
  │   │     from: 0x939599136029208E46A1b79d485E12fec94c7056,
  │   │     to:   TransparentUpgradeableProxy: [0x46e18572…],
  │   │     value: 60610300000000000000
  │   ├─ BEP20USDT::approve(PancakeRouter: [0x10ED43C7…], 10307335639681778901944)
  │   ├─ PancakeRouter::swapExactTokensForTokensSupportingFeeOnTransferTokens(...)
  │   └─ OLY::transferFrom / Treasury flows

(Source: pre-incident user trace, artifacts/root_cause/data_collector/iter_4/tx/56/0xd6915f9e…/trace.cast.log.)

In this benign case, a user calls the router via the proxy, supplying their own address as the owner argument, and the router uses transferFrom(owner, proxy, amount) to pull USDT into the proxy and swap into OLY.

The vulnerability arises because Unresolved_6f73978a:

  • Does not constrain arg3 (owner) to equal msg.sender or any whitelisted account.
  • Relies solely on existing ERC-20 allowances from owner to the proxy and on owner’s balance.
  • Uses the proxy as the spender in transferFrom, so any pre-existing allowance[owner][proxy] is sufficient.

Therefore, any unprivileged caller who can call Unresolved_6f73978a via the proxy, and who knows a list of addresses with non-zero USDT balances and approvals to the proxy, can:

  • Set arg2 = BEP20USDT,
  • Set arg3 = victim_address,
  • Set arg4 to the treasury/router address, and
  • Choose an amount up to the victim’s balance/allowance, causing BEP20USDT.transferFrom(victim, proxy, amount) to succeed, followed by swaps and OLY transfers, without any victim interaction at attack time.

Detailed Root Cause Analysis

The ACT opportunity is instantiated at block 74081238 via a single adversary-crafted transaction:

  • Adversary transaction:
    • Chain: BNB Chain (chainid = 56)
    • Tx hash: 0x827e23d6dc6bfdc06d6062f53203fd1ca6f3cc00f8bad21ea6bf9aa7d9b349ed
    • From: EOA 0xf10395d26262b92cc95729f274965868bd7f938b
    • Type: contract-creation with zero native value

Seed traces for this transaction show the following sequence:

[46711210] → new <unknown>@0x85616b87D4D5313D4Cb1f91370AE5A2297b3a2AB(...)
  ...
  ├─ TransparentUpgradeableProxy::fallback(0x6f73978a...)
  │   ├─ 0x7719…b46F::6f73978a(..., token = BEP20USDT, owner = victim, ...)
  │   │   ├─ BEP20USDT::transferFrom(victim, TransparentUpgradeableProxy: [0x46e18572…], amount)
  │   │   ├─ BEP20USDT::approve(PancakeRouter: [0x10ED43C7…], ...)
  │   │   ├─ PancakeRouter::swapExactTokensForTokensSupportingFeeOnTransferTokens(...)
  │   │   └─ OLY/treasury flows
  ├─ (pattern repeats for many victim EOAs)

(Source: seed transaction trace, artifacts/root_cause/seed/56/0x827e23d6…/trace.cast.log and artifacts/root_cause/data_collector/iter_2/tx/56/0x827e23d6…/trace.cast.log.)

The helper contract 0x8561…2AB is created by the adversary EOA and immediately used within the same transaction to drive multiple Unresolved_6f73978a calls via the proxy. For each victim address with a pre-existing BEP20USDT approval to the proxy, the helper:

  • Sets the token parameter to BEP20USDT.
  • Sets the owner parameter to the victim address.
  • Triggers BEP20USDT.transferFrom(victim, proxy, amount) under the victim’s existing allowance and balance.
  • Causes the proxy to approve PancakeRouter and swap USDT into OLY.
  • Routes OLY and/or USDT proceeds into adversary-controlled aggregation addresses.

The BEP20USDT balance diff for the seed transaction quantifies these flows. Example entries:

{
  "erc20_balance_deltas": [
    {
      "token": "0x55d398326f99059ff775485246999027b3197955",
      "holder": "0xa78493b667b72322f3b0595d159d6d885e3ecd87",
      "before": "63829659024483467636128",
      "after": "0",
      "delta": "-63829659024483467636128",
      "contract_name": "BEP20USDT"
    },
    {
      "token": "0x55d398326f99059ff775485246999027b3197955",
      "holder": "0xcaaf3c41a40103a23eeaa4bba468af3cf5b0e0d8",
      "before": "43124190617983759518989497",
      "after": "43131693242983759518989498",
      "delta": "7502625000000000000001",
      "contract_name": "BEP20USDT"
    }
  ]
}

(Source: seed balance diff, artifacts/root_cause/seed/56/0x827e23d6…/balance_diff.json.)

These entries are representative:

  • Victim EOAs such as 0xA78493b667B72322F3b0595d159D6d885e3ecd87 lose essentially all of their USDT in the seed transaction.
  • Adversary aggregation addresses such as 0xcaaf3c41a40103a23eeaa4bba468af3cf5b0e0d8 show large positive USDT deltas.

The adversary cluster’s net BEP20USDT profit is computed by summing BEP20USDT before/after balances across:

  • EOA 0xf10395d2… (attacker EOA).
  • Four aggregation addresses:
    • 0xfd36427acaf5865f1683dd6fca8a5b8d83661ff9
    • 0x60a558581e9875f1b3402bc45526cf71c0366207
    • 0xe1cd1288683cd8496236343faea21fa22da5e20d
    • 0xcaaf3c41a40103a23eeaa4bba468af3cf5b0e0d8

From balance_diff.json:

  • Cluster BEP20USDT before: 43405848.105313391278059015 USDT.
  • Cluster BEP20USDT after: 43585492.667341569955812428 USDT.
  • Net delta: 179644.562028178677753413 USDT.

Native BNB gas for the seed transaction is measured separately:

  • EOA 0xf10395d2… loses exactly 0.003748100774962014 BNB in native_balance_deltas.
  • Gas is not converted to USDT; the reference asset here is USDT only.

The ACT success predicate is therefore:

  • Reference asset: USDT (BEP20USDT on BNB Chain).
  • Adversary address cluster: {0xf10395d2…, 0xfd3642…, 0x60a558…, 0xe1cd12…, 0xcaaf3c…}.
  • Success condition: value_delta_in_reference_asset > 0 for the cluster, which holds with +179644.562028178677753413 USDT.

Adversary Flow Analysis

The adversary flow proceeds in two main stages.

1. Normal user flow via Unresolved_6f73978a (baseline)

The pre-incident transaction 0xd6915f9eb544d1a92cf3ec935250225869b72b787aa42064897c40f5e6555d3a shows a benign user interacting with the router:

  • Caller: a regular EOA with USDT balance and an approval to the proxy.
  • Call path:
    • TransparentUpgradeableProxy::fallback(0x6f73978a...)
    • 0x7719…b46F::6f73978a(...) via delegatecall
    • BEP20USDT.transferFrom(user, proxy, amount)
    • BEP20USDT.approve(PancakeRouter, amount')
    • PancakeRouter.swapExactTokensForTokensSupportingFeeOnTransferTokens(USDT → OLY)
    • OLY flows through treasury and staking contracts.

This trace confirms that:

  • Users are expected to approve the proxy to spend their USDT.
  • Unresolved_6f73978a reads the owner from calldata and uses it as the from in transferFrom.
  • The function is part of normal router usage and not a hidden backdoor.

2. Adversary helper deployment and batched USDT draining

In the seed transaction 0x827e23d6…, the adversary EOA:

  1. Deploys helper contract 0x85616b87D4D5313D4Cb1f91370AE5A2297b3a2AB via contract-creation.
  2. Uses the helper, within the same transaction, to:
    • Call TransparentUpgradeableProxy::fallback(0x6f73978a...) repeatedly.
    • For each call, set:
      • token = BEP20USDT (0x55d3983…)
      • owner = victim_EOA
      • Router/treasury address parameters to OLY treasury components.
    • Trigger BEP20USDT.transferFrom(victim, proxy, amount) using existing allowance[victim][proxy] and balanceOf(victim).
    • Approve PancakeRouter 0x10ED43C718714eb63d5aA57B78B54704E256024E to spend USDT from the proxy.
    • Swap drained USDT into OLY on PancakePair 0x6865704FF097b1105Ed42B8517020e14Fe9A2ABD.
    • Route OLY and potentially USDT proceeds into aggregation addresses.

The seed trace logs show many repetitions of this pattern, each time with a different victim EOA. The balance diff confirms that:

  • Victims lose their USDT in a single block and end with zero or near-zero balances.
  • The adversary cluster receives all of the net positive USDT.

Post-incident txlists for the four large aggregation addresses in artifacts/root_cause/data_collector/iter_4/address/56/ are empty JSON arrays across windows 74500000–76000000 (or 74150000–76000000), indicating that within the collected range, there are no outbound transactions from these addresses. The stolen USDT remains concentrated at these addresses in the observed blocks.

Impact & Losses

The total quantified loss in BEP20USDT is:

  • 179644.562028178677753413 USDT

This amount is computed directly from BEP20USDT balance deltas in balance_diff.json for:

  • The adversary-related cluster {0xf10395d2…, 0xfd3642…, 0x60a558…, 0xe1cd12…, 0xcaaf3c…}.
  • The victim EOAs drained via the helper’s repeated Unresolved_6f73978a calls.

Key impact points:

  • Dozens of BEP20USDT holders who had approved proxy 0x46e18572… see large negative BEP20USDT deltas and post-tx balances of zero in balance_diff.json.
  • The adversary cluster’s combined BEP20USDT holdings increase by 179644.562028178677753413 USDT.
  • The adversary EOA 0xf10395d2… pays approximately 0.003748100774962014 BNB in gas, recorded in native_balance_deltas.
  • Within the post-incident txlist windows for the four aggregation addresses, there are no outgoing transactions; the stolen USDT remains in those addresses in the observed data.

The loss figure is entirely on-chain and does not depend on off-chain pricing oracles; values are computed in unit terms of BEP20USDT (18 decimals) from balance diffs.

References

  • [1] Seed transaction metadata and BEP20USDT/OLY balance diffs for 0x827e23d6…:
    • artifacts/root_cause/seed/56/0x827e23d6dc6bfdc06d6062f53203fd1ca6f3cc00f8bad21ea6bf9aa7d9b349ed/
  • [2] Router implementation decompile and ABI (implementation 0x77190F0C8e97514c4fd3895FB5B4fb464961b46F behind proxy 0x46e18572…):
    • artifacts/root_cause/data_collector/iter_1/contract/56/0x77190F0C8e97514c4fd3895FB5B4fb464961b46F/decompile/
  • [3] Pre-incident user transaction trace invoking Unresolved_6f73978a via the proxy:
    • artifacts/root_cause/data_collector/iter_4/tx/56/0xd6915f9eb544d1a92cf3ec935250225869b72b787aa42064897c40f5e6555d3a/trace.cast.log
  • [4] Post-incident txlists for large BEP20USDT aggregation addresses:
    • artifacts/root_cause/data_collector/iter_4/address/56/

These references are all derived from canonical on-chain data (RPC queries, logs, traces) and publicly available contract metadata, and collectively support the ACT opportunity characterization and the protocol-level root cause.