Calculated from recorded token losses using historical USD prices at the incident time.
0x827e23d6dc6bfdc06d6062f53203fd1ca6f3cc00f8bad21ea6bf9aa7d9b349ed0x77190f0c8e97514c4fd3895fb5b4fb464961b46fBSC0x46e185726084e8dc8a3ee8bd955e476237d49074BSC0x55d398326f99059ff775485246999027b3197955BSC0x544028231562a43b106fbceca722b65cb5c861b0BSCBNB 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.
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 , which delegates calls to router implementation . Many EOAs had granted standard BEP20USDT approvals to the proxy, enabling it to move their USDT in normal staking or swapping operations.
0x46e185726084e8Dc8a3eE8bd955e476237d490740x77190F0C8e97514c4fd3895FB5B4fb464961b46FThe ACT pre-state σ_B is BNB Chain state at block 74081237, immediately before the adversary seed transaction at block 74081238. It consists of:
0x46e18572… delegating to router implementation 0x7719…b46F.This pre-state is evidenced by:
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 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/).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:
b[1]:
txhash: 0x827e23d6dc6bfdc06d6062f53203fd1ca6f3cc00f8bad21ea6bf9aa7d9b349edfrom: 0xf10395d26262b92cc95729f274965868bd7f938btransferFrom calls through the established proxy/implementation.No privileged roles, admin keys, or private orderflow are required to realize this strategy.
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.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:
arg3 (owner) to equal msg.sender or any whitelisted account.owner to the proxy and on owner’s balance.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:
arg2 = BEP20USDT,arg3 = victim_address,arg4 to the treasury/router address, andBEP20USDT.transferFrom(victim, proxy, amount) to succeed, followed by swaps and OLY transfers, without any victim interaction at attack time.The ACT opportunity is instantiated at block 74081238 via a single adversary-crafted transaction:
chainid = 56)0x827e23d6dc6bfdc06d6062f53203fd1ca6f3cc00f8bad21ea6bf9aa7d9b349ed0xf10395d26262b92cc95729f274965868bd7f938bSeed 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:
BEP20USDT.transferFrom(victim, proxy, amount) under the victim’s existing allowance and balance.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:
0xA78493b667B72322F3b0595d159D6d885e3ecd87 lose essentially all of their USDT in the seed transaction.0xcaaf3c41a40103a23eeaa4bba468af3cf5b0e0d8 show large positive USDT deltas.The adversary cluster’s net BEP20USDT profit is computed by summing BEP20USDT before/after balances across:
0xf10395d2… (attacker EOA).0xfd36427acaf5865f1683dd6fca8a5b8d83661ff90x60a558581e9875f1b3402bc45526cf71c03662070xe1cd1288683cd8496236343faea21fa22da5e20d0xcaaf3c41a40103a23eeaa4bba468af3cf5b0e0d8From balance_diff.json:
43405848.105313391278059015 USDT.43585492.667341569955812428 USDT.179644.562028178677753413 USDT.Native BNB gas for the seed transaction is measured separately:
0xf10395d2… loses exactly 0.003748100774962014 BNB in native_balance_deltas.The ACT success predicate is therefore:
{0xf10395d2…, 0xfd3642…, 0x60a558…, 0xe1cd12…, 0xcaaf3c…}.value_delta_in_reference_asset > 0 for the cluster, which holds with +179644.562028178677753413 USDT.The adversary flow proceeds in two main stages.
The pre-incident transaction 0xd6915f9eb544d1a92cf3ec935250225869b72b787aa42064897c40f5e6555d3a shows a benign user interacting with the router:
TransparentUpgradeableProxy::fallback(0x6f73978a...)0x7719…b46F::6f73978a(...) via delegatecallBEP20USDT.transferFrom(user, proxy, amount)BEP20USDT.approve(PancakeRouter, amount')PancakeRouter.swapExactTokensForTokensSupportingFeeOnTransferTokens(USDT → OLY)This trace confirms that:
Unresolved_6f73978a reads the owner from calldata and uses it as the from in transferFrom.In the seed transaction 0x827e23d6…, the adversary EOA:
0x85616b87D4D5313D4Cb1f91370AE5A2297b3a2AB via contract-creation.TransparentUpgradeableProxy::fallback(0x6f73978a...) repeatedly.token = BEP20USDT (0x55d3983…)owner = victim_EOABEP20USDT.transferFrom(victim, proxy, amount) using existing allowance[victim][proxy] and balanceOf(victim).0x10ED43C718714eb63d5aA57B78B54704E256024E to spend USDT from the proxy.0x6865704FF097b1105Ed42B8517020e14Fe9A2ABD.The seed trace logs show many repetitions of this pattern, each time with a different victim EOA. The balance diff confirms that:
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.
The total quantified loss in BEP20USDT is:
179644.562028178677753413 USDTThis amount is computed directly from BEP20USDT balance deltas in balance_diff.json for:
{0xf10395d2…, 0xfd3642…, 0x60a558…, 0xe1cd12…, 0xcaaf3c…}.Unresolved_6f73978a calls.Key impact points:
0x46e18572… see large negative BEP20USDT deltas and post-tx balances of zero in balance_diff.json.179644.562028178677753413 USDT.0xf10395d2… pays approximately 0.003748100774962014 BNB in gas, recorded in native_balance_deltas.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.
0x827e23d6…:
artifacts/root_cause/seed/56/0x827e23d6dc6bfdc06d6062f53203fd1ca6f3cc00f8bad21ea6bf9aa7d9b349ed/0x77190F0C8e97514c4fd3895FB5B4fb464961b46F behind proxy 0x46e18572…):
artifacts/root_cause/data_collector/iter_1/contract/56/0x77190F0C8e97514c4fd3895FB5B4fb464961b46F/decompile/Unresolved_6f73978a via the proxy:
artifacts/root_cause/data_collector/iter_4/tx/56/0xd6915f9eb544d1a92cf3ec935250225869b72b787aa42064897c40f5e6555d3a/trace.cast.logartifacts/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.