Analyzing the BetterBank Exploit: Flaws, Financial Impact, and Lessons Learned
| Shelf | AI & ML |
|---|---|
| Date in | |
| Readers | 921 |
The BetterBank exploit showcased critical flaws in its reward system, resulting in a $1.4 million loss. A detailed analysis highlights the root causes and necessary mitigations.

Executive Summary
Between August 26 and 27, 2025, BetterBank, a decentralized finance (DeFi) protocol built on the PulseChain network, was exploited, leading to a severe financial hit of around $5 million due to liquidity manipulation and flawed reward minting logic. Despite the recovery of approximately $2.7 million after negotiations with the attacker, a net loss of about $1.4 million remained. At the heart of this incident was a design flaw within the swapExactTokensForFavorAndTrackBonus function, which was intended to mint ESTEEM tokens upon the successful completion of swaps but lacked validation checks for legitimate liquidity pools.

This vulnerability had been previously flagged by Zokyo in a security audit, published before the attack, but due to misunderstandings and a perceived low severity rating, the BetterBank team failed to address it comprehensively. This event emphasizes the dire importance of robust security audits, accurate communication of vulnerabilities, and the implementation of multilayered security strategies within blockchain technologies.
This article analyzes the incident's causes, the financial repercussions, and the forensics surrounding the malicious activities involved in the exploit.
Incident Overview
Incident Timeline
The groundwork for the BetterBank exploit was laid weeks prior, with a security audit conducted by Zokyo in July 2025 that explicitly identified a crucial vulnerability related to the protocol's bonus reward system. The audit report, eventually released to the public, warned about the exploit avenue, noting that a “malicious user can trade bogus tokens to qualify for bonus FAVOR through the UniswapWrapper.” This critical finding, however, was downplayed, categorized as “Informational,” and attributed a resolution status, leading the development team to overlook the necessary patch implementation.
On August 26, the exploit initiated, prompting BetterBank's team to react swiftly by draining all remaining FAVOR liquidity pools to secure undamaged assets. Notably, the team offered a 20% bounty to the attacker in exchange for the return of funds. The negotiation bore fruit the following day, resulting in the return of about 550 million DAI tokens, which exceptionally mitigated what could have been a total loss.
Financial Impact
The financial ramifications of the incident were substantial, with an initial loss tallying around $5 million. This figure stemmed from the exploitation of liquidity pools and included substantial amounts of stablecoins and assets specific to the PulseChain ecosystem, such as 891 million DAI, 9.05 billion PLSX, and 7.40 billion WPLS tokens.
Following the return of 550 million DAI through successful negotiation, the net loss stood at approximately $1.4 million—a significant decrease but still a painful blow for users and stakeholders. The fluctuation in asset values amidst the broader market volatility was noted but consistently pointed to these rounded figures.
| Financial Metric | Value | Details |
| Initial Total Loss | ~$5,000,000 | Identifies total assets siphoned during the hack event. |
| Assets Drained | 891M DAI, 9.05B PLSX, 7.40B WPLS | Specific tokens and amounts taken from the protocol's liquidity pools. |
| Assets Returned | ~$2,700,000 (550M DAI) | Assets successfully reclaimed from the attacker post negotiations. |
| Net Loss | ~$1,400,000 | Total unrecovered financial loss incurred by the protocol and its users. |
Protocol Description and Vulnerability Analysis
The BetterBank protocol operates as a decentralized lending platform on the PulseChain network and is based on a dual-token model designed to incentivize liquidity provision and participant engagement. Within this framework, the primary token is designated as FAVOR, while ESTEEM acts as a reward token. Users earn ESTEEM for contributing liquidity to FAVOR on decentralized exchanges (DEXs). However, the incentive mechanism harbored a critical design flaw that opened it up to exploitation.
This vulnerability emerged not merely as a coding error, but as a fundamental architectural oversight. By linking rewards to an unverified output condition—the presence of FAVOR tokens post-swap—the protocol neglected essential security measures, allowing malicious actors to create counterfeit environments mimicking trusted ones. Such tokenomics failures often overlook the requisite validation protocols necessary to ensure the security of incentivization structures.
The crux of the vulnerability resided in the faulty logic of BetterBank’s smart contracts, particularly within the swapExactTokensForFavorAndTrackBonus function. This function aimed to track swaps and subsequently mint rewards. However, its logic was notably incomplete, only confirming that a swap outputted FAVOR without validating the legitimacy of the swap’s origin. This oversight permitted attackers to manipulate the system by triggering bonus minting without authorization.
Additionally, the architecture allowed for ESTEEM tokens, minted as rewards, to be convertible back into FAVOR tokens. This created a feedback loop where the newfound ESTEEM could generate more FAVOR, which in turn facilitated additional swaps and subsequent ESTEEM mints. The design flaws interactively compounded the exploitation risks, giving the attacker a mechanism to generate ostensibly boundless rewards while draining digital reserves.
Exploit Breakdown
The attack predominantly targeted the bonus minting capabilities embedded in the favorPLS.sol contract, notably executed through the logBuy() function and corresponding tax mechanisms. The essential vulnerabilities within the protocol involved:
- File:
favorPLS.sol - Vulnerable Function:
logBuy(address user, uint256 amount) - Supporting Function:
calculateFavorBonuses(uint256 amount) - Tax Logic:
_transfer()Function
Within the logBuy function, the protocol only confirmed whether the user was an approved buy wrapper, lacking checks on the legitimacy of the trading pair or liquidity source. This failure left the door open for exploitation.
function logBuy(address user, uint256 amount) external {
require(isBuyWrapper[msg.sender], "Only approved buy wrapper can log buys");
(uint256 userBonus, uint256 treasuryBonus) = calculateFavorBonuses(amount);
pendingBonus[user] += userBonus;
esteem.mint(treasury, treasuryBonus);
emit EsteemBonusLogged(user, userBonus, treasuryBonus);
}The tax mechanism was intended to apply only to transfers from recognized market pairs, thereby excluding illicit, unauthorized liquidity pairs from taxation. Consequently, attackers could bypass the imposed sell tax for untaxed bulk swaps.

function _transfer(address sender, address recipient, uint256 amount) internal override {
uint256 taxAmount = 0;
if (_isTaxExempt(sender, recipient)) {
super._transfer(sender, recipient, amount);
return;
}
// Transfer to Market Pair is likely a sell to be taxed
if (isMarketPair[recipient]) {
taxAmount = (amount * sellTax) / MULTIPLIER;
}
if (taxAmount > 0) {
super._transfer(sender, treasury, taxAmount);
amount -= taxAmount;
}
super._transfer(sender, recipient, amount);
}Step-by-Step Attack Reconstruction
The assault on BetterBank unfolded as a meticulously orchestrated series of transactions rather than a single act. It commenced with the attacker utilizing a flash loan, which allows borrowing large amounts of capital without collateral as long as repayment occurs within the same transaction. Using this mechanism, the attacker acquired substantial resources to manipulate the protocol effectively.
This startup capital targeted the DAI-PDAIF liquidity pool, a vital component of the BetterBank ecosystem. The subsequent depletion of this pool effectively eroded the protocol's defenses and enabled the attacker to procure vast volumes of PDAIF tokens, essential for executing reward minting operations.
As the attacker drained the real liquidity pool, they transitioned into deploying a newly created token, which had zero value. The attacker then took advantage of PulseX's permissionless environment to construct a fake liquidity pool that paired their worthless token with PDAIF.
This fraudulent pool was crucial to the exploit, as it allowed the attacker to control both sides of the trading pair and manipulate liquidity and pricing without impacting the wider market. This exploit was further facilitated by the protocol’s applicable tax logic, which only imposed penalties on recognized, whitelisted liquidity pairs. For the attacker's new pool, which had no such status, operations could proceed without the burden of taxation, significantly bolstering profit margins.
With the bogus liquidity pool in place, the attacker initiated the final phase of their operation: engaging in a reward minting cycle by executing rapid swaps between their counterfeit token and PDAIF. Each successful swap triggered the vulnerable swapExactTokensForFavorAndTrackBonus function within BetterBank’s contract, which, due to its lack of pool validation, incorrectly minted large quantities of ESTEEM tokens for each illicit swap performed.
The process involved stages:
- Invocation of
swapExactTokensForFavorAndTrackBonus() - Call to
logBuy()function - Execution of
calculateFavorBonuses() - Minting of ESTEEM tokens (up to 44% bonus)
- Circumvention of fake LP sell taxes
The newly minted ESTEEM tokens were then quickly converted back to FAVOR, facilitating further swaps and stimulating an endless recursive loop that perplexingly allowed the attacker to amass an unrealistic supply of rewards while depleting the protocol’s genuine liquidity. Ultimately, the attack yielded approximately 891 million DAI, 9.05 billion PLSX, and 7.40 billion WPLS, critically undermining the protocol’s integrity and stability. The successful execution of this multilayered assault exemplified how a single, pivotal design flaw could culminate in devastating outcomes.
Mitigation Strategy
The incident presents several lessons in security that, if implemented, could have preemptively thwarted the exploit.
Firstly, protocols should emphasize the importance of validating liquidity pool pairs before executing swaps. Enhanced verification checks would enable the identification of unauthorized or invalid LPs.
function logBuy(address user, uint256 amount) external {
require(isBuyWrapper[msg.sender], "Only approved buy wrapper can log buys");
// ADD: LP pair validation
require(isValidLPPair(msg.sender), "Invalid LP pair");
require(hasMinimumLiquidity(msg.sender), "Insufficient liquidity");
require(isVerifiedPair(msg.sender), "Unverified trading pair");
// ADD: Amount limits
require(amount
Secondly, the system's tax logic should be revised to apply universally to all transfers, preventing circumvention by unrecognized entities.
function _transfer(address sender, address recipient, uint256 amount) internal override {
uint256 taxAmount = 0;
if (_isTaxExempt(sender, recipient)) {
super._transfer(sender, recipient, amount);
return;
}
// FIX: Apply tax to ALL transfers, not just market pairs
if (isMarketPair[recipient] || isUnverifiedPair(recipient)) {
taxAmount = (amount * sellTax) / MULTIPLIER;
}
if (taxAmount > 0) {
super._transfer(sender, treasury, taxAmount);
amount -= taxAmount;
}
super._transfer(sender, recipient, amount);
}
Lastly, imposing transaction limits for rewards can be an effective deterrent against excessive exploitation. A daily bonus cap could be introduced to regulate transactions and mitigate large-scale one-time attacks.
mapping(address => uint256) public lastBonusClaim;
mapping(address => uint256) public dailyBonusLimit;
uint256 public constant MAX_DAILY_BONUS = 10000 * 1e18; // 10K ESTEEM per day
function logBuy(address user, uint256 amount) external {
require(isBuyWrapper[msg.sender], "Only approved buy wrapper can log buys");
// ADD: Rate limiting
require(block.timestamp - lastBonusClaim[user] > 1 hours, "Rate limited");
require(dailyBonusLimit[user]
On-chain Forensics and Fund Tracing
The forensic analysis of on-chain activities left a clear trail post-exploit. Following the extraction of assets from PulseChain, the attacker proceeded to convert the stolen DAI, PLSX, and WPLS into more liquid assets and subsequently bridged approximately $922,000 worth of ETH from PulseChain to Ethereum's mainnet. This operation was conducted through a secondary address, likely established to obscure the primary attacker’s identity.
The ultimate phase of fund laundering involved utilizing a crypto mixer, such as Tornado Cash, effectively anonymizing the fund source and complicating tracking efforts. The tracing process faced barriers largely due to inadequate or inaccessible public-facing block explorers for the PulseChain network, which demonstrates the challenges inherent to on-chain forensic investigations. In such cases, the usage of open-source explorers like Blockscout becomes vital to fortifying transparency and data resiliency.
| On-Chain Entity | Address | Description |
| Primary Attacker EOA | 0x48c9f537f3f1a2c95c46891332E05dA0D268869B | The main externally owned account employed to instigate the attack. |
| Secondary Attacker EOA | 0xf3BA0D57129Efd8111E14e78c674c7c10254acAE | The address utilized to bridge assets to the Ethereum network. |
| Attacker Helper Contracts | 0x792CDc4adcF6b33880865a200319ecbc496e98f8, etc. | A cadre of contracts leveraged by the attacker to execute the exploit. |
| PulseXRouter02 | 0x165C3410fC91EF562C50559f7d2289fEbed552d9 | The PulseX decentralized exchange router contract involved in the exploit. |
Further examination of the exploiter's helper contracts unveiled a multilayered attack architecture, utilizing a factory contract pattern (0x792CDc4adcF6b33880865a200319ecbc496e98f8) characterized by 18,219 bytes of dynamic bytecode deployed in real-time. This embedded contract featured critical components, including two simple functions for initialization and cleanup, alongside a complex flash loan callback function, compatible with standard DeFi protocols such as Aave and dYdX.
contract BetterBankExploitContract {
function main() external {
// Initialize memory
assembly {
mstore(0x40, 0x80)
}
// Revert if ETH is sent
if (msg.value > 0) {
revert();
}
// Check minimum calldata length
if (msg.data.length > 224;
// Dispatch to appropriate function
if (selector == 0x51cff8d9) {
// Function: withdraw(address)
withdraw();
} else if (selector == 0x529d699e) {
// Function: likely exploit execution
executeExploit();
} else if (selector == 0x920f5c84) {
// Function: executeOperation(address[],uint256[],uint256[],address,bytes)
// This is a flash loan callback function!
executeOperation();
} else {
revert();
}
}
// Function 0x51cff8d9 - Withdraw function
function withdraw() internal {
// Implementation would be in the bytecode
// Likely withdraws profits to attacker address
}
// Function 0x529d699e - Main exploit function
function executeExploit() internal {
// Implementation would be in the bytecode
// Contains the actual BetterBank exploit logic
}
// Function 0x920f5c84 - Flash loan callback
function executeOperation(
address[] calldata assets,
uint256[] calldata amounts,
uint256[] calldata premiums,
address initiator,
bytes calldata params
) internal {
// This is the flash loan callback function
// Contains the exploit logic that runs during flash loan
}
}Through this dissection, it became apparent that the design flaws in BetterBank’s architecture enabled the exploitation by unvalidated discrepancies in reward minting, tax evasion tactics, and manipulation via counterfeit trading volume. The attacker leveraged flash loans of 50 million DAI and 7.14 billion PLP tokens to not only drain real liquidity pools but also create fraudulent pools with minimal liquidity, conducting numerous iterations of fraudulent trading to trigger disproportionate ESTEEM rewards, thereby achieving significant profits amounting to around 891 million DAI via arbitrage.
Proof of Concept Snippets
To further elucidate the vulnerabilities resulting in the attack, we dove into code snippets provided by Zokyo researchers.
Initially, a fake liquidity pool pair was created where the attacker invented a counterfeit token by manipulating the codebase. This structure rendered it possible for fraudulent liquidity pairs to exist.
function _createFakeLPPair() internal {
console.log("--- Step 1: Creating Fake LP Pair ---");
vm.startPrank(attacker);
// Create the pair
fakePair = factory.createPair(address(favorToken), address(fakeToken));
console.log("Fake pair created at:", fakePair);
// Add initial liquidity to make it "legitimate"
uint256 favorAmount = 1000 * 1e18;
uint256 fakeAmount = 1000000 * 1e18;
// Transfer FAVOR to attacker
vm.stopPrank();
vm.prank(admin);
favorToken.transfer(attacker, favorAmount);
vm.startPrank(attacker);
// Approve router
favorToken.approve(address(router), favorAmount);
fakeToken.approve(address(router), fakeAmount);
// Add liquidity
router.addLiquidity(
address(favorToken),
address(fakeToken),
favorAmount,
fakeAmount,
0,
0,
attacker,
block.timestamp + 300
);
console.log("Liquidity added to fake pair");
console.log("FAVOR in pair:", favorToken.balanceOf(fakePair));
console.log("FAKE in pair:", fakeToken.balanceOf(fakePair));
vm.stopPrank();
}Next, the attacker would approve the fake LP pair in the allowedDirectPair mapping, thus allowing it to pass system checks for executing the bulk swap transactions.
function _approveFakePair() internal {
console.log("--- Step 2: Approving Fake Pair ---");
vm.prank(admin);
routerWrapper.setAllowedDirectPair(address(fakeToken), address(favorToken), true);
console.log("Fake pair approved in allowedDirectPair mapping");
}These initial steps set the stage for the exploitation, allowing developers to complete effective swaps and earn ESTEEM bonuses.
function _executeExploit() internal {
console.log("--- Step 3: Executing Exploit ---");
vm.startPrank(attacker);
uint256 exploitAmount = 100 * 1e18; // 100 FAVOR per swap
uint256 iterations = 10; // 10 swaps
console.log("Performing %d exploit swaps of %d FAVOR each", iterations, exploitAmount / 1e18);
for (uint i = 0; i
Finally, several checks validate the success of the exploit.
function _verifyExploitSuccess() internal {
uint256 finalFavorBalance = favorToken.balanceOf(attacker);
uint256 finalEsteemBalance = esteemToken.balanceOf(attacker);
uint256 esteemMinted = esteemToken.totalSupply() - initialEsteemBalance;
console.log("Attacker's final FAVOR balance:", finalFavorBalance / 1e18);
console.log("Attacker's final ESTEEM balance:", finalEsteemBalance / 1e18);
console.log("Total ESTEEM minted during exploit:", esteemMinted / 1e18);
// Verify the attack was successful
assertGt(finalEsteemBalance, 0, "Attacker should have ESTEEM tokens");
assertGt(esteemMinted, 0, "ESTEEM tokens should have been minted");
console.log("EXPLOIT SUCCESSFUL!");
console.log("Attacker gained ESTEEM tokens without legitimate trading activity");
}
Conclusion
The BetterBank exploit serves as a compelling case study in the interplay of technology and security within decentralized finance. It underscores the significance of robust validation mechanisms in smart contracts, revealing that the vulnerability was fundamentally a design flaw and not a mere coding oversight. The chain of events, from the initial identification of the flaw to the subsequent exploit and recovery efforts, highlights the essential nature of effective communication within teams responsible for protocol security.
While partial recovery of funds was a positive aspect, the foundational lessons from BetterBank’s experience resonate deeply: every line of code and design decision carries weight. Security in the DeFi space requires proactive engagement and a commitment to layered protective strategies amid an evolving landscape of threats.



