JFIN Exploit Analysis
On December 20, 2025, The JFIN LCBridgev2Token was exploited on the Binance Smart Chain, resulting in the loss of approximately $15,000. Let’s take a closer look at how the attack was carried out.
Original Attacker : https://etherscan.io/address/0xb27794423b2fd4492887098166d62de142637751
Vulnerable Contract : https://etherscan.io/address/0x3EbFd0EFC49a27fb633bd56013E4220EBC2c3C6d#tokentxns
Attack Tx : https://etherscan.io/tx/0xf867d1d7164ac9178d81696c989f65e817b8cab14850345ab3a1f99bbe547210
Analysis
This contract allows users to stake JFIN into a shared liquidity pool. When users stake, their tokens are transferred into the contract, their staked balance is recorded, and the total pool size (tvl) increases. The contract tracks a “reward per staked token” value (rtr) to distribute rewards fairly among all stakers.
Rewards primarily come from swap fees. When someone uses the bridge swap, the contract collects a small fee. Part of that fee goes to the treasury, and the rest is added to the staker rewards pool. As more fees are collected over time, rtr increases, meaning each staker earns more based on their stake amount and duration.
Users can claim rewards anytime with claimReward(). The contract calculates how much the user earned since their last update, then transfers the tokens. If the contract lacks sufficient tokens at that moment, it pays what it can and records the unpaid portion as debt (debtReward—calculated in getReward) for the user to claim later.
The getReward function already returns debtReward plus new earned rewards. The problem lies in stake. Before updating the stake data, it executes: userInfo[account].debtReward += getReward(account); But getReward(account) already includes userInfo[account].debtReward. This means the old debtReward is added again into debtReward. An attacker can call stake multiple times with small amounts to inflate the debtReward amount.
In swap, the contract calls _cutFee. This step collects a fee and adds part of it to totalReward.
When someone later calls stake, the contract updates rtr with the pending reward using: new rtr = totalReward - prevReward. After this update, prevReward becomes totalReward, and rtr becomes the new baseline. Since the new rtr is always greater than or equal to the current rtr, rewards always increase with rtr (or totalReward).
The attacker first staked an amount of JFIN, then called swap to increase totalReward. After that, they called stake 20 times with amount 1 to inflate the reward. Finally, they called claimReward to drain the manipulated reward.
Conclusion
This vulnerability exploits a critical flaw in the reward accounting logic of the staking contract. The double-counting issue in the stake function allows attackers to exponentially inflate their debtReward balance by repeatedly staking minimal amounts. Each call compounds the existing debt into the new calculation, creating artificial rewards without legitimate basis. Furthermore, calculating rewards based on totalReward instead of available funds also enables exploitation.






