All incidents

InugamiStaking Expired-Pool Debt Initialization Bypass (BSC)

Share
Mar 03, 2026 05:30 UTCAttackLoss: 13.9 WBNBManually checked1 exploit txWindow: Atomic
Estimated Impact
13.9 WBNB
Label
Attack
Exploit Tx
1
Addresses
1
Attack Window
Atomic
Mar 03, 2026 05:30 UTC → Mar 03, 2026 05:30 UTC

Exploit Transactions

TX 1BSC
0xa487da310b02dfa3e6da2d9b3c797b656957924f4b08e38ed256cfeed48dbbca
Mar 03, 2026 05:30 UTCExplorer

Victim Addresses

0x2001144a0485b0b3748a167848cdd73837345d73BSC

Loss Breakdown

13.9WBNB

Similar Incidents

Root Cause Analysis

InugamiStaking Expired-Pool Debt Initialization Bypass (BSC)

1. Incident Overview TL;DR

Transaction 0xa487da310b02dfa3e6da2d9b3c797b656957924f4b08e38ed256cfeed48dbbca on BSC block 84377206 is an ACT exploit against InugamiStaking (0x2001144a0485b0b3748a167848cdd73837345d73).

A fresh, unprivileged EOA (0x43c2f458e3aa73dcfd872144ded5c7faf56e33f8) deployed an executor contract (0x20a8047fd8b23db7446041c32c442a77eb46f989) and, in one transaction, acquired LP, staked LP, reactivated an expired reward pool with a 1 wei WBNB top-up, claimed historical rewards, then exited and transferred profit back to the EOA.

Root cause: expired reward pools bypass user debt initialization in _updateUserDebt, while streamReward() can reactivate those pools without resetting stale accRewardPerShare. This allows a newly staked user to claim rewards accrued before stake time.

2. Key Background

The staking system uses accumulator-based reward accounting:

  • accRewardPerShare tracks cumulative reward per stake unit.
  • Per-user debt (_userDebt) must be initialized against current accumulator at entry time.

Security-critical expectation: after stake, user debt for each reward PID should be set to balance * accRewardPerShare / 1e36, so claims only include post-entry accrual.

In this incident, reward PID0 (WBNB) was expired but retained a very large stale accumulator and significant reserves. That state made debt initialization gating exploitable.

3. Vulnerability Analysis & Root Cause Summary

This is an ATTACK-class logic/accounting exploit, not a privileged-access incident. The vulnerable invariant is debt initialization consistency at user entry across all active accounting dimensions.

The verified InugamiStaking source confirms _updateUserDebt only updates debt when endRewardTimestamp >= block.timestamp. For expired pools, debt is left unchanged (zero for a new staker). streamReward() is permissionless and can reactivate an expired pool by adding any positive reward amount, while preserving stale accumulator context. After reactivation, claim uses current balance and stale high accumulator against zero debt, producing an oversized payout. Trace evidence confirms the exact sequence stake -> transfer(1 wei WBNB) -> streamReward -> claim -> unstake.

4. Detailed Root Cause Analysis

4.1 Code-Level Breakpoint

Victim code (verified source for 0x2001144a0485b0b3748a167848cdd73837345d73) shows both enabling conditions:

function streamReward() external {
    _updatePools(false, address(0));
    ...
    if (newRewards > 0) {
        ...
        rewardInfo.reserves += newRewards;
        rewardInfo.endRewardTimestamp = lastRewardTimestamp + WINDOW_LENGTH;
    }
}

function _updateUserDebt(address user) internal {
    for (uint256 i = 0; i < rewardTokensCount; ++i) {
        if (
            rewardInfos[i].rewardToken != address(0) &&
            rewardInfos[i].endRewardTimestamp >= block.timestamp
        ) {
            _userDebt[i][user] =
                (balanceOf[user] * rewardInfos[i].accRewardPerShare) / 1e36;
        }
    }
}

If a reward PID is expired when stake executes, debt is not initialized for that PID.

4.2 Exploitable Pre-State (Immediately Before Exploit)

State snapshot at block 0x5077e75 (pre-state) shows PID0 expired but still carrying large stale accounting state and reserves:

reward0 token: 0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c
accRewardPerShare: 911232950638852218698941779818023669046
reserves: 13904954155454625823
endRewardTimestamp: 1649459132  (expired)
WBNB bal: 13904954155454625823

4.3 On-Chain Exploit Sequence

Collector trace confirms the deterministic sequence and key values:

0x2001144a...::stake(15259494452769803)
WBNB::transfer(0x2001144a..., 1)
0x2001144a...::streamReward()
0x2001144a...::claim(0x20A8047f..., [0])
  WBNB::transfer(0x20A8047f..., 13904954155454625145)
0x2001144a...::unstake(15259494452769803)

Post-state at block 0x5077e76 shows pool reactivated (endRewardTimestamp pushed forward) and WBNB reserve nearly drained:

reward0 reserves: 679
reward0 endRewardTimestamp: 1773120610
WBNB bal: 679

4.4 Invariant Violation Realization

Intended invariant: for each reward PID, a new staker should have debt initialized to current accumulator-weighted balance at stake time.

Observed breakpoint: because PID0 was expired at stake time, debt remained zero; after reactivation, claim was computed against stale high accumulator and paid out historical rewards, violating temporal reward attribution.

5. Adversary Flow Analysis

  1. Stage 1: Deploy executor with seed capital.
  • Sender EOA: 0x43c2f458e3aa73dcfd872144ded5c7faf56e33f8
  • Deployed contract: 0x20a8047fd8b23db7446041c32c442a77eb46f989
  • Same transaction (0xa487da31...) funds and executes the attack path atomically.
  1. Stage 2: Acquire LP stake asset.
  • Executor performs Pancake router swaps/add-liquidity to obtain INUGAMI/WBNB LP (0xe7989a82615b68c09b6fc0d1d24c95551a47e0cf).
  1. Stage 3: Trigger accounting exploit and cash out.
  • Stake LP into InugamiStaking.
  • Transfer 1 wei WBNB to staking.
  • Call streamReward() to reactivate expired PID0.
  • Call claim(...,[0]) to receive 13904954155454625145 wei WBNB.
  • Unstake LP, unwrap WBNB to BNB, forward BNB to the controlling EOA.

All calls are public/permissionless and feasible by any unprivileged actor.

6. Impact & Losses

Victim-side loss:

  • WBNB drained from staking pool: 13.904954155454625144 WBNB (13904954155454625144 wei), leaving 679 wei.

Attacker-side realized gain:

  • EOA native balance delta: +13895178308441569254 wei (+13.895178308441569254 BNB) in the exploit transaction.

Affected victim contract:

  • InugamiStaking at 0x2001144a0485b0b3748a167848cdd73837345d73.

7. References

  • Exploit transaction: 0xa487da310b02dfa3e6da2d9b3c797b656957924f4b08e38ed256cfeed48dbbca (BSC, block 84377206).
  • Victim contract: 0x2001144a0485b0b3748a167848cdd73837345d73.
  • Attacker EOA: 0x43c2f458e3aa73dcfd872144ded5c7faf56e33f8.
  • Attacker executor: 0x20a8047fd8b23db7446041c32c442a77eb46f989.
  • Verified source (Etherscan V2 contract source API for victim contract).
  • Collected evidence used in validation:
    • artifacts/collector/seed/56/0xa487da310b02dfa3e6da2d9b3c797b656957924f4b08e38ed256cfeed48dbbca/trace.cast.log
    • artifacts/collector/seed/56/0xa487da310b02dfa3e6da2d9b3c797b656957924f4b08e38ed256cfeed48dbbca/balance_diff.json
    • artifacts/auditor/iter_0/staking_state_pre_post.txt