Root Cause
Symbiosis's BridgeV2 contract on BNB Chain failed to adequately validate that the claimed BTC deposit amount matched actual BTC locked on the Bitcoin side. The fee-verification path could be bypassed, allowing the minting function to issue syBTC orders of magnitude larger than the real deposit.
Based on incident reports, the vulnerable fee-subtraction logic likely resembled:
// BridgeV2.sol (Symbiosis, BNB Chain) — conceptual reconstruction
function mintSyBTC(
uint256 btcDepositAmount, // relayer-supplied, not verified against BTC chain proof
uint256 fee,
bytes calldata relayerSig
) external {
// BUG: relayer sig covers btcDepositAmount but fee computation is exploitable
// Possible underflow (pre-0.8) or separate bypass allowing fee >= depositAmount
uint256 toMint = btcDepositAmount - fee; // results in huge toMint
require(verifyRelayerSig(relayerSig, btcDepositAmount, fee), "bad sig");
syBTC.mint(msg.sender, toMint); // mints 46B tokens against 330-sat deposit
}
The core issue: the amount of BTC locked on the Bitcoin side was never verified on-chain. The contract trusted a relayer-signed value. Once the fee-verification check was bypassed (likely via arithmetic edge case or a separate code path), the attacker could specify an arbitrarily large btcDepositAmount and receive a correspondingly massive syBTC mint.
Attack Steps
| Step | Action | Detail |
|---|---|---|
| 1 | Minimal deposit | Deposit 330 satoshis (~$0.25) to Symbiosis BTC bridge |
| 2 | Exploit fee path | Craft BridgeV2 call exploiting fee-verification bypass; claim 46.1B syBTC |
| 3 | Rapid multi-chain liquidation | Execute 12 transactions across BNB Chain, Ethereum, Rootstock in ~4 minutes |
| 4 | Convert to WBTC | Drain liquidity pools by swapping syBTC for WBTC and other assets |
| 5 | Proceed & exit | Attacker takes ~$770K; Symbiosis halts bridge |
Impact
- Chains: BNB Chain, Ethereum, Rootstock
- Protocol: Symbiosis (BridgeV2 contract)
- Asset minted: 46.1 billion syBTC (completely unbacked)
- Estimated loss: ~$770,000 (Symbiosis protocol estimate); ~$336,000 (DeFiLlama confirmed WBTC withdrawn)
- Bridge status: Bitcoin Bridge taken offline for full rewrite and independent audit; post-mortem published September 15
- Partial recovery: 15 BTC recovered into multisig; 20% bounty offered but not claimed before deadline
Lessons for Auditors
- Bridge minting must be gated by verifiable proof. A contract minting tokens that represent locked assets on another chain must verify a cryptographic proof of that lock (e.g., SPV proof for BTC bridges, or a threshold-signed attestation scheme). Relayer signatures on attacker-supplied amounts are not sufficient.
- Fee arithmetic is a critical attack surface. Fee subtraction on caller-supplied values is prone to underflow (Solidity < 0.8) and manipulation. Use checked arithmetic, validate
fee < depositAmount, and independently bound the fee range. - Fuzz bridge entry points across the full uint256 range. Extreme values (0, 1, type(uint256).max, type(uint256).max - 1) and values near fee thresholds must all be tested. Automated fuzzing (Foundry, Echidna) would likely have caught this.
- Rate-limit minting per block. A per-block mint cap would have drastically limited the damage from 46B tokens to a much smaller exploitable amount, buying time for detection.