DBXen Exploit Analysis
On March 11, 2026, DBXen was exploited through a vulnerability on the custom logic, resulting in the loss of approximately $149,000. Let’s take a closer look at how the attack was carried out.
Original Attacker :
https://bscscan.com/address/0xe92fa2a5fef535479a91ab9ed90b26256ff276f1
https://etherscan.io/address/0x63150ac8e35c6c685e93ee4d7d5cb8eafb2f016b
Vulnerable Contract :
https://bscscan.com/address/0x9caf6c4e5b9e3a6f83182befd782304c7a8ee6de
https://etherscan.io/address/0xf5c80c305803280b587f8cabbccdc4d9bf522abd
Attack Tx :
https://bscscan.com/tx/0xe66e54586827d6a9e1c75bd1ea42fa60891ad341909d29ec896253ee2365d366
https://etherscan.io/tx/0x914a5af790e55b8ea140a79da931fc037cb4c4457704d184ad21f54fb808bc37
Analysis
The contract is a reward distribution system where users burn XEN tokens to earn DBXen rewards and a share of protocol fees. The system operates in discrete time intervals called cycles. During each cycle, users can burn tokens via burnBatch, and their contribution is tracked through accCycleBatchesBurned. At the end of a cycle, rewards are distributed proportionally based on the number of batches burned relative to the total batches burned in that cycle.
In addition to rewards, users can earn fees generated by the protocol. These fees are distributed based on a user’s accumulated rewards and stake. The function updateStats plays a central role by settling all pending rewards, fees, and stake transitions for a user whenever they interact with the contract (e.g., claiming rewards or fees).
The vulnerability arises from inconsistent use of msg.sender and _msgSender() across the contract. Specifically, different parts of the same logical flow attribute user actions to different addresses.
In bunBatch, the contract uses _msgSender() when updating accCycleBatchesBurned, meaning the burned amount is credited to the actual user.
However, when interacting with the XEN token contract, the burn mechanism uses msg.sender, which corresponds to the forwarder in a meta-transaction context. As a result, the burn operation is executed on behalf of the forwarder, not the user.
First, the attacker calls burnBatch via a trusted forwarder. This results in accCycleBatchesBurned being incremented for the attacker, while lastActiveCycle is updated for the forwarder. At this point, the system already holds inconsistent state.
Next, the attacker calls either claimRewards or claimFees. Both of these functions internally call updateStats, which attempts to calculate pending rewards for the user.
Inside updateStats, the contract checks whether the current cycle is greater than lastActiveCycle[account] and whether the user has non-zero burned batches. Because lastActiveCycle[attacker] was never updated, this condition remains true even after rewards have already been calculated.
As a result, the contract repeatedly assumes that the attacker’s burn contribution has not yet been processed and recalculates rewards every time updateStats is invoked.
Conclusion
The root cause of the vulnerability is inconsistent identity handling in a meta-transaction context. By mixing msg.sender and _msgSender() across different parts of the same execution flow, the contract attributes related state updates to different addresses. This leads to a breakdown in internal accounting, allowing an attacker to repeatedly claim rewards from a single action and ultimately drain funds from the protocol.






