Allbridge Core BNB Chain BUSD/USDT Virtual-Balance Withdrawal Mismatch Drain (2023-04-01)
- Name: Allbridge Core BNB Chain BUSD/USDT virtual-balance withdrawal mismatch drain
- Date: 2023-04-01
- Protocol: Allbridge Core
- Chain: BNB Chain
- Category: virtual-balance withdrawal mismatch / single-sided pool accounting failure / bridge-liquidity accounting bug
- Loss: about
$570kin the main exploit transaction and about$650kacross the April 1-2 attack sequence before Allbridge fully contained the issue - Summary: Allbridge Core’s BNB Chain stablecoin pools were not ordinary two-sided AMMs. Each pool held one real stablecoin reserve and one internal virtual
vUSDbalance used to move value across the bridge. The flaw was in how those pools handled liquidity withdrawals under imbalance: the old design minted and burntvUSDas if nominal token amounts stayed 1:1 economically equivalent, even when the pool had already drifted away from balance. That let the attacker use flash-loaned capital to become both a large LP and a swapper, take a deliberate loss on a huge BUSD-side withdrawal that pushed the pool into an extreme artificial imbalance, and then exploit the broken pricing state by turning about$40kof BUSD into roughly$800kofvUSDvalue on the next swap leg. The profit did not come from the first withdrawal itself; it came from the fact that the withdrawal retired too little of the pool’s internal liability relative to the real liquidity it removed. - Trigger / entry point:
- Allbridge Core exposed public liquidity deposit, withdrawal, and swap paths on BNB Chain pools that internally priced one real stablecoin against virtual
vUSD. - The attacker interacted directly with the smart contracts in exploit transaction
0x7ff1364c3b3b296b411965339ed956da5d17058f3164425ce800d64f1aef8210. - Public analysis tied the main exploit to attacker address
0x2b3cff12c02625518deb0af14684999fb6e3e360and later activity to0xc578d755cd56255d3ff6e92e1b6371ba945e3984. - Public writeups identified the affected BNB Chain pool contracts as
0x179aad597399b9ae078acfe2b746c09117799ca0and0xb19cd6ab3890f18b662904fd7a40c003703d2554, with Allbridge contract0x68784ffaa6ff05e3e04575df77960dc1d9f42b4ainvolved in the flow.
- Allbridge Core exposed public liquidity deposit, withdrawal, and swap paths on BNB Chain pools that internally priced one real stablecoin against virtual
- Root cause:
- Allbridge’s old pool logic assumed it was safe to mint and burn the same nominal amount of virtual
vUSDon deposit and withdrawal. - That approximation worked tolerably when pools were close to balanced, but it broke once a pool was meaningfully skewed.
- Under the old logic, an LP could burn shares and withdraw more economically meaningful liquidity than the protocol should have allowed for the amount of internal value being retired.
- After such an overgenerous withdrawal, the pool’s remaining real-reserve-versus-virtual-balance state made subsequent swaps massively mispriced.
- The exploit therefore combined two roles that the protocol implicitly assumed would stay economically separate: the same actor first manufactured pathological imbalance as an LP and then consumed the resulting false quote as a swapper.
- Allbridge’s old pool logic assumed it was safe to mint and burn the same nominal amount of virtual
- Exploit path:
- The attacker used flash-loaned capital to seed large temporary liquidity positions in the BUSD and USDT pools on BNB Chain.
- Allbridge’s own postmortem says the attacker deposited about
$5Minto the BUSD pool and$2Minto the USDT pool. - The attacker then swapped about
$500kfrom USDT into BUSD, moving both pools slightly off balance. - With that initial imbalance in place, the attacker withdrew most of the BUSD-side liquidity position, around
$4.8M, at a visible loss. - That loss-making withdrawal was the setup leg: because the pool burnt virtual
vUSDincorrectly, it left the BUSD pool far more imbalanced than honest proportional accounting should have allowed. - The attacker next swapped about
$40kof BUSD back toward USDT. In Allbridge’s reconstructed numbers, the artificially distorted pool state treated that leg as worth roughly$800kof internalvUSDvalue. - The attacker then withdrew the remaining liquidity from both pools, repaid the flash loans, and kept the spread created by the broken accounting.
- A second similar attack later extracted additional funds before Allbridge fully stopped the exploit path.
- What the attacker needed to be true:
- The old Allbridge Core pool implementation had to remain live on BNB Chain with the flawed
vUSDwithdrawal logic. - The attacker had to be able to alternate LP and swap actions quickly enough that honest rebalancing flow would not heal the pool first.
- Pools had to be liquid enough that a temporary multi-million-dollar LP position could materially reshape the reserve state.
- The protocol had to let the same actor both create the imbalance and consume the resulting quote within one tightly coupled sequence.
- Shutdown of the UI or backend alone could not stop the exploit because the core contracts remained directly callable.
- The old Allbridge Core pool implementation had to remain live on BNB Chain with the flawed
- Technical anatomy worth remembering:
- This was not a bridge-verifier failure, signer compromise, or forged message incident. The cross-chain brand obscures that the break happened in the bridge’s local same-chain liquidity accounting.
- The attacker’s high-signal move was accepting a loss on the huge withdrawal leg because that withdrawal corrupted the next quote more than enough to pay back the setup cost.
- The broken accounting lived in the relationship among LP shares, real stablecoin reserves, and internal
vUSDliabilities. Once that relationship drifted, the pool began quoting fiction against real reserves. - The incident is a useful reminder that
virtualbalances are still solvency-critical state. If a protocol lets them go out of sync with economically backed value, the next swap or bridge quote will happily cash out the difference. - It also shows why disabling frontends is not a real containment plan for an onchain accounting bug. Allbridge had to raise bridge fees to
100%because direct contract calls still made the exploit viable after the interface and backend were turned off.
- Representative transactions and addresses:
- Main exploit transaction:
0x7ff1364c3b3b296b411965339ed956da5d17058f3164425ce800d64f1aef8210 - Publicly flagged failed transaction:
0x18e5f822cc85567c1d7d8fdbc89e62e17ec11fd48f5b4aab831895f8850300e7 - Main attacker address:
0x2b3cff12c02625518deb0af14684999fb6e3e360 - Later associated attacker address in public writeups:
0xc578d755cd56255d3ff6e92e1b6371ba945e3984 - Publicly identified affected pool addresses:
0x179aad597399b9ae078acfe2b746c09117799ca0,0xb19cd6ab3890f18b662904fd7a40c003703d2554 - Allbridge contract highlighted by public analysis:
0x68784ffaa6ff05e3e04575df77960dc1d9f42b4a
- Main exploit transaction:
- Response / mitigation:
- Allbridge first disabled the UI and backend, but the team later wrote that this was insufficient because attackers could keep calling the contracts directly.
- As an emergency brake, the protocol raised bridge fees to
100%, making the exploit path economically unattractive until a fuller fix shipped. - In the relaunch, Allbridge rewrote deposit and withdrawal accounting so virtual
vUSDbecame fully or proportionally backed by deposited stablecoins instead of being minted and burnt as a nominal sidecar. - The team also capped withdrawals at the value represented by the burned LP tokens, added explicit reserve tracking, and introduced a special rebalancer authority for exceptional reserve-migration events.
Why this incident matters
- It is a sharp example of a bridge-adjacent exploit whose decisive failure was neither message verification nor key management, but same-chain pool accounting.
- It preserves a recurring lesson that shows up across many DeFi systems: a deliberately loss-making setup leg can still be rational if it pushes internal accounting far enough out of line to make the next pricing step absurdly favorable.
- It also broadens the exploit corpus beyond standard two-sided AMM bugs by showing how virtual settlement balances in single-sided bridge pools can become the real solvency boundary.
- The sharper preserved healthy-side boundary is that
virtual balance existsshould not have been treated asthat much economically backed value still remains after this LP exit. Allbridge needed one reserve-backed liability object that withdrawals and next-swap quotes were both forced to consume.
Three reserve / liability promotions this incident collapsed
-
Some pool-local reserve and virtual-liability state moved
- The attacker first nudged the BUSD/USDT pools off balance, then used a very large BUSD-side LP withdrawal to remove real reserves while the pool burnt too little of the corresponding internal
vUSDliability. - That only proves local state changed. By itself it should not have been enough to prove that the post-withdrawal reserve/liability mix was still economically coherent or that the next quoted swap should trust it.
- The attacker first nudged the BUSD/USDT pools off balance, then used a very large BUSD-side LP withdrawal to remove real reserves while the pool burnt too little of the corresponding internal
-
Allbridge promoted that distorted state into canonical post-withdrawal balance-sheet truth
- The old accounting path effectively published one authoritative story about
remaining real reserves versus remaining virtual value, even though the burn path had under-retired the liability side. - This was the decisive middle mistake: the protocol treated a locally distorted state as if it were the correct remaining balance sheet for the pool.
- The old accounting path effectively published one authoritative story about
-
The next swap spent against that published story as if it were money-good
- The attacker then converted about
$40kof BUSD into roughly$800kof internalvUSDvalue because the next user-facing quote honored the distorted post-withdrawal state. - That is stronger again: downstream swap logic inherited live reserve-spending authority from a balance-sheet story the withdrawal path should never have been allowed to publish.
- The attacker then converted about
The recurring review mistake is to collapse those steps into one vague explanation like the pool got imbalanced and pricing moved. Healthy systems keep local state changed, the protocol published one canonical reserve/liability story, and downstream paths may now spend against that story visibly separate.
Pattern tags:
- Under-retired virtual liability: the large BUSD-side withdrawal removed too much real reserve relative to the amount of internal
vUSDliability it retired. - Loss-making setup leg: the attacker knowingly accepted a bad withdrawal price because the corrupted next quote was worth far more.
- Same-actor role coupling: one address acted as dominant LP and immediate swapper, so the same party both created the pathological imbalance and monetized it before anyone could rebalance the pools.
- Design companions: virtual-balance-withdrawal-mismatch, reserve-backed-claim-truth-security-object, and lp-exit-and-next-quote-balance-sheet-coherence.
Why the exploit worked
- Allbridge’s old pool design treated nominal withdrawal amounts and virtual-liability retirement as if they stayed economically equivalent even after the pool had drifted far from balance.
- The protocol never forced a stricter
current backed valuecalculation before letting LP-share burns remove scarce real stablecoin reserves. - The same post-withdrawal state then immediately became user-facing swap truth, so the attacker could cash out the accounting gap through the next quote instead of waiting for any slower rebalance process.
- Liquidity was deep enough, and direct contract access open enough, that a flash-loaned attacker could perform the whole
seed liquidity -> skew pool -> take loss on withdrawal -> consume broken quotesequence in one tightly coupled operation.
Detection and audit pivots
- Test whether burning x% of LP supply can ever remove more than x% of economically backed pool value under stressed imbalance, not only in balanced states.
- Compare the exact state object consumed by LP exits with the exact state object consumed by the next swap quote. If they are not the same post-settlement balance sheet, the pool is too trusting.
- Ask whether a visibly loss-making withdrawal can still be rational because it makes the next swap dramatically better for the same actor. That is a strong smell that withdrawal accounting and quote accounting disagree about value.
- Track virtual balances as liabilities rather than convenience variables. If the code can remove real reserves without shrinking the economically matching internal liability, the protocol is already publishing fictional solvency.
- Treat UI shutdowns as irrelevant to exploitability when the real issue sits in directly callable onchain accounting paths.
Failure-prevention checklist
- Keep one canonical post-settlement balance sheet for each pool: real stablecoin reserves, backed virtual
vUSD, LP supply, and any reserve-migration state should all update together before the next quote is exposed. - Derive withdrawals from current backed value rather than nominal deposit history. Burning LP shares should retire the same economic object that the next swap would otherwise spend.
- Enforce a hard
burned LP value is the maximum removable valuebound under every reachable imbalance, not only under near-balanced conditions. - Treat same-actor LP / swapper coupling as a first-class adversarial sequence. If one address can worsen imbalance and immediately consume the resulting quote, the design must still remain reserve-bounded or deliberately stage one side of the flow.
- Track reserve deficits and reserve migration explicitly. If backing has effectively moved to other chains or pools, local virtual balances and local withdrawal rights must stop pretending that value is still fully available.
- Add invariant tests for
loss-making setup leg, profitable follow-up quotesequences. If a withdrawal that looks irrational in isolation can still make money overall, the accounting boundary is already too weak. - Make emergency controls work at the contract layer, not only the interface layer. Direct contract calls should face pause paths, quote clamps, withdrawal throttles, or fee controls that assume the UI may already be irrelevant.
- Rehearse degraded-mode topology changes ahead of time. Allbridge’s later
one asset per chainchoice is a reminder that pool layout itself can be part of the mitigation when multi-pool same-transaction coupling is otherwise too easy to abuse.
Audit prompts
- After this withdrawal executes, what exact real reserve remains, what exact virtual liability remains, and what exact quote would still be honest one stack frame later?
- Can burning x% of LP supply ever remove more than x% of economically backed value once the pool is already skewed?
- Do LP exits and swaps read the same post-withdrawal balance sheet, or can the quote path still consume value the burn path failed to retire?
- Can one address become a dominant temporary LP, force imbalance, and monetize the next quote in the same transaction or block?
- Where does the protocol record reserve deficits created by bridge flow, and how do those deficits constrain local withdrawals and quotes before organic rebalancing happens?
- If a withdrawal is visibly loss-making, what proves that the same actor cannot recover much more than that loss on the very next swap leg?
- Which onchain controls still work if attackers bypass the frontend and call pool contracts directly during the incident window?
- What telemetry would page operators when one large exit suddenly makes the next small swap economically impossible under any coherent balance sheet?
Lessons that should already be standard
- Virtual balances are liabilities, not explanatory fiction. If they influence withdrawals or quotes, they belong inside the solvency boundary.
- A loss-making setup leg is not comforting when the next quote can overpay by more. Rational attackers happily lose on one state transition to get paid on the next.
- LP-exit math is quote-security math in single-sided pools. If the burn path and pricing path consult different books, the protocol is already paying from inconsistent balance sheets.
- Bridge-adjacent pool accounting bugs are still local solvency bugs. The dangerous trust boundary here was not message verification but the pool’s own reserve-versus-virtual-liability accounting.
- Pool topology can be a security control. If the same design lets one actor couple multiple assets or roles too tightly in one transaction, reducing that coupling can be a real mitigation, not merely a product simplification.
- Frontend shutdown is not containment for a directly callable accounting flaw. If the contracts remain live, the exploit path remains live.
- The healthy design question is simple: after any LP exit, what exact value was actually retired, and what exact value is the next user still allowed to spend?
Internal linkages
- Core recurring pattern: virtual-balance-withdrawal-mismatch — Allbridge is the clean bridge-style single-sided-pool exemplar where LP burns retired too little internal
vUSDliability relative to the real reserve they removed. - Positive-design companion: reserve-backed-claim-truth-security-object — the healthier question is what exact reserve-backed liability object LP shares, virtual
vUSD, and user-facing quotes were all supposed to reference after each withdrawal. - Narrower quote-coherence companion: lp-exit-and-next-quote-balance-sheet-coherence — the sharper follow-up is how one loss-making LP exit and the immediately following swap quote should have been forced to read the same post-withdrawal balance sheet instead of letting the quote path spend value the burn path failed to retire.
- Adjacent comparison: spartan-protocol-current-balance-liquidity-share-inflation-drain-2021-05-01 — both incidents let LP-style exits corrupt the next economic state, but Spartan misattributed ambient balances as already-recognized reserve backing while Allbridge under-retired a virtual liability inside a single-sided bridge pool.
- Adjacent comparison: uranium-finance-v2-k-invariant-scaling-mismatch-drain-2021-04-28 — another pool-accounting failure, but Uranium broke the invariant check inside a two-sided AMM
swap()path rather than the LP-burn accounting of a single-sided virtual-balance pool. - Adjacent comparison: harvest-finance-curve-y-pool-share-price-manipulation-2020-10-26 — both attacks used a state-distortion setup leg before cashing out through later pricing, but Harvest manipulated trusted valuation inputs while Allbridge corrupted the pool’s own withdrawal accounting.
Control surface
-
The leverage sat in Allbridge Core’s BNB Chain pool deposit/withdraw math, the relation between real stablecoin reserves and internal
vUSDbalances, and the protocol decision to let the same live pool state decide both LP exit value and the next swap quote. -
The deeper control surface was reserve-backed liability accounting itself: Allbridge lacked one canonical post-withdrawal balance sheet that simultaneously answered
how much real value may this LP remove?andhow much virtual value may the next swap still trust? -
Allbridge did not merely suffer from
flash loans. It let LP-share burns, virtual liabilities, and same-chain stablecoin pricing stop referring to the same economic balance sheet. -
Sources:
- https://allbridge.medium.com/allbridge-core-updates-following-the-relaunch-9f7716eeb5da
- https://medium.com/neptune-mutual/how-was-allbridge-exploited-956a05f3cb58
- https://blog.solidityscan.com/allbridge-hack-analysis-improper-business-logic-564fbadf38b2/
- https://bscscan.com/tx/0x7ff1364c3b3b296b411965339ed956da5d17058f3164425ce800d64f1aef8210
-
Last reviewed: 2026-08-01 UTC