StepHeroNFTs Referral Reentrancy
Exploit Transactions
0xef386a69ca6a147c374258a1bf40221b0b6bd9bc449a7016dbe5240644581877Victim Addresses
0x9823e10a0bf6f64f59964be1a7f83090bf5728abBSCLoss Breakdown
Similar Incidents
Pepe Claim Reentrancy
39%BCT Referral Treasury Drain
37%Wukong Staking Reentrancy Drain
37%YYDS Referral Overpayment
36%T3913 Pair-Skim Referral Drain
35%BSC staking pool reentrancy drain
35%Root Cause Analysis
StepHeroNFTs Referral Reentrancy
1. Incident Overview TL;DR
In BNB Smart Chain transaction 0xef386a69ca6a147c374258a1bf40221b0b6bd9bc449a7016dbe5240644581877 at block 46843424, an unprivileged attacker cluster used the StepHero marketplace at 0x9823e10a0bf6f64f59964be1a7f83090bf5728ab as both seller and referral recipient. The attacker borrowed 1000 WBNB from Pancake V3 pool 0x172fcd41e0913e95784454622d1c3724f546f849, unwrapped it to native BNB, bought its own ERC1155 listing through a separate helper contract, and then recursively claimed the marketplace referral reward in native BNB.
The root cause is a checks-effects-interactions failure in the marketplace referral payout path. The victim contract transfers native BNB to msg.sender before zeroing the caller's claimable referral balance, so an attacker-controlled receive hook can reenter claimReferral(address(0)) and drain the same credit repeatedly. The seed balance diff shows the profit receiver 0xfb1cc1548d039f14b02cff9ae86757edd2cdb8a5 ending the transaction with a net gain of 137.876033699999999999 BNB.
2. Key Background
StepHeroNFTs is an unverified marketplace contract that supports ERC1155 listings and native-BNB purchases. The collected seed artifacts show that native BNB was an enabled payment path in the historical state, which matters because the vulnerable payout branch is only reachable when the referrer claims rewards with token == address(0).
The attack also relied on public infrastructure rather than privileged access. Pancake V3 provided permissionless flash liquidity through pool 0x172fcd41e0913e95784454622d1c3724f546f849, and the marketplace listing and purchase functions were callable by arbitrary addresses. Referral rewards were tracked per (token, claimer) pair, so once the attacker made its seller contract the referrer, the same contract became eligible to claim the new BNB reward.
The relevant adversary cluster in the seed transaction consists of:
- EOA
0xfb1cc1548d039f14b02cff9ae86757edd2cdb8a5, which funded deployment and received final profit. - Wrapper/orchestrator
0xd4c80700ca911d5d3026a595e12aa4174f4cacb3, created in the seed transaction. - Seller/referrer helper
0xb4c32404de3367ca94385ac5b952a7a84b5bdf76, which received repeated BNB payouts and seller proceeds. - Buyer helper
0x8f327e60fb2a7928c879c135453bd2b4ed6b0fe9, which executed the purchase as a distinct buyer.
3. Vulnerability Analysis & Root Cause Summary
This incident is an ATTACK-class ACT opportunity caused by reentrancy in the marketplace's native-BNB referral claim path. The core invariant is straightforward: for any payout token and claimant, claimReferral(token) must reduce the stored claimable amount to zero before any external transfer is made. If that invariant holds, the same reward cannot be claimed twice in one transaction.
The recorded breakpoint is the victim's decompiled claimReferral(address) implementation (func_06B7 in the auditor's analysis), where the contract loads the referral balance for (token, msg.sender), calls the payout helper func_2D1E(msg.sender, amount, token), and only then writes the storage slot back to zero. When token is the zero address, the payout helper performs a raw native-BNB transfer to msg.sender. That means control returns to attacker code before state is cleared.
The on-chain trace confirms the runtime consequence of that ordering. After the attacker self-buys its listing, the marketplace sends a 3 BNB referral payout to the seller/referrer helper. That helper's fallback immediately reenters claimReferral(address(0)), causing the same 3 BNB amount to be paid again and again before the marketplace finally completes the original call stack.
4. Detailed Root Cause Analysis
The attack sequence starts from block 46843423, the pre-state immediately before the exploit transaction. The seed metadata and trace show a single adversary-crafted transaction containing the complete exploit path:
0xb4c32404de3367ca94385ac5b952a7a84b5bdf76 -> 0x172fcd41e0913e95784454622d1c3724f546f849 flash(...)
0xb4c32404de3367ca94385ac5b952a7a84b5bdf76 -> 0x9823e10a0bf6f64f59964be1a7f83090bf5728ab 0xded4de3a(...)
0x8f327e60fb2a7928c879c135453bd2b4ed6b0fe9 -> 0x9823e10a0bf6f64f59964be1a7f83090bf5728ab 0x60acd67f(...), value 1000 BNB
Those calls establish the seller/referrer position, execute the self-purchase, and create a fresh native-BNB referral balance. The root cause becomes observable immediately afterward. In the nested call tree, the marketplace repeatedly enters claimReferral(0x0000000000000000000000000000000000000000) while the attacker helper repeatedly receives native BNB in its fallback:
0xB4C32404de3367Ca94385ac5b952a7a84B5BdF76::fallback{value: 3000000000000000000}()
0x9823E10A0bF6F64F59964bE1A7f83090bf5728aB::claimReferral(0x0000000000000000000000000000000000000000)
0xB4C32404de3367Ca94385ac5b952a7a84B5BdF76::fallback{value: 3000000000000000000}()
0x9823E10A0bF6F64F59964bE1A7f83090bf5728aB::claimReferral(0x0000000000000000000000000000000000000000)
emit ReferralClaimed(param0: 0xB4C32404de3367Ca94385ac5b952a7a84B5BdF76, param1: 0x0000000000000000000000000000000000000000, param2: 3000000000000000000)
This pattern recurs throughout the seed trace. Earlier trace offsets also show repeated value transfers of exactly 3000000000000000000 wei from the marketplace to 0xb4c32404de3367ca94385ac5b952a7a84b5bdf76, followed later by a 970000000000000000000 wei seller settlement. The referral payout therefore occurs before the marketplace has finalized internal accounting for the same referral balance.
The attack succeeds because the attacker controls both the credited referrer and the code that receives native BNB. By the time the marketplace eventually zeroes the referral slot, the contract has already honored the same claim many times. The seed balance diff shows the concrete victim-side loss:
{
"address": "0x9823e10a0bf6f64f59964be1a7f83090bf5728ab",
"before_wei": "138699325579296300000",
"after_wei": "699325579296300000",
"delta_wei": "-138000000000000000000"
}
That loss is consistent with the repeated 3 BNB payouts plus normal marketplace settlement. The same balance diff records the attacker's EOA profit receiver with a 137876033699999999999 wei net gain after gas, which matches the incident summary in root_cause.json.
5. Adversary Flow Analysis
The adversary flow is a single-transaction flash-loan-funded self-trade with recursive referral claiming.
- The attacker EOA
0xfb1c...b8a5submits the exploit transaction and deploys a wrapper that immediately invokes the seller/referrer helper. - The seller/referrer helper calls Pancake V3
flashand receives1000 WBNB, then unwraps it into native BNB. - The same helper lists an ERC1155 item on StepHero through selector
0xded4de3a, making itself the seller. - The helper deploys a distinct buyer contract and funds it with
1000 BNBso the marketplace purchase is not blocked by seller checks. - The buyer contract calls the marketplace purchase selector
0x60acd67fwith the seller/referrer helper set as the referrer. This credits a3 BNBnative referral reward to the helper. - The helper calls
claimReferral(address(0)). Each native payout reaches the helper fallback, which immediately callsclaimReferral(address(0))again while the same stored reward remains uncleared. - After the recursive loop, the helper receives the normal
970 BNBseller proceeds, rewraps enough BNB to repay1000.1 WBNBto Pancake V3, and forwards the remaining profit to the original EOA.
The seed trace and balance diff show that each of these steps happened on-chain in one atomic execution path. No privileged account, private key compromise, or non-public component was required, so the incident is correctly classified as an ACT opportunity.
6. Impact & Losses
The measurable loss is native BNB drained from the StepHero marketplace referral pool. The validated impact from root_cause.json and the seed balance diff is:
- Token:
BNB - Amount:
137876033699999999999wei - Decimal:
18
This equals 137.876033699999999999 BNB net profit to the attacker cluster after gas. The marketplace's native balance fell from 138.6993255792963 BNB to 0.6993255792963 BNB during the exploit transaction, demonstrating that the referral accounting flaw had direct treasury impact.
7. References
- Seed transaction metadata:
0xef386a69ca6a147c374258a1bf40221b0b6bd9bc449a7016dbe5240644581877 - Victim marketplace:
0x9823e10a0bf6f64f59964be1a7f83090bf5728ab - Flash-loan pool:
0x172fcd41e0913e95784454622d1c3724f546f849 - Profit receiver EOA:
0xfb1cc1548d039f14b02cff9ae86757edd2cdb8a5 - Seller/referrer helper:
0xb4c32404de3367ca94385ac5b952a7a84b5bdf76 - Buyer helper:
0x8f327e60fb2a7928c879c135453bd2b4ed6b0fe9 - Supporting evidence artifacts:
- Seed metadata
- Seed trace
- Seed balance diff