← Dashboard
BNB Smart ChainChain ID: 56
PMA Case #—
PancakeBunny
AMM 기반 LP 가격 오라클 조작으로 6,972,455 BUNNY를 무한 발행, 114,631 WBNB (~$58.1M) 탈취
LP Price Oracle ManipulationFlash Loan ×8Multi-Tx (Setup + Exploit)Yield Aggregator
1. 프로토콜 의존성 구조도
All
Step 1: Flash Loan
Step 2: LP 전송
Step 3: 가격 조작
Step 4: Reward 탈취
Step 5: Dump & Repay
전체 공격 흐름: 7개 PCS 풀에서 2,323,376 WBNB + ForTube에서 2,961,750 USDT 차입 → v2 Pool에 유동성 추가(7,744 BNB + 2.96M USDT), 144,445 LP 잔류 → v1 Pool에서 2,315,631 WBNB→3,826,047 USDT 스왑으로 가격 붕괴 → getReward()→BunnyMinter가 잔류 LP까지 소각→조작가 기반 6,972,455 BUNNY 민팅 → BUNNY 매도 + 플래시 론 상환 → 114,631 WBNB 순이익.
2. 종합 대시보드
2-1. Transaction Info
Date / Time (UTC)2021-05-19 22:34:28
Attack TypeLP Price Oracle Manipulation
Flash Loan BNB2,323,376 WBNB (~$1.18B)
Flash Loan USDT2,961,750 USDT (ForTube)
Attacker Profit114,631.54 WBNB (~$58.1M) + 697,245 BUNNY
Victim ImpactBUNNY $146 → $6.17 (−95.8%), 총 공급 1M→9M
2-2. Attack Execution Flow
Setup — 별도 Tx (0x88fc...71a)
LP 예치 (미끼 설치)
1 BNB → 9.275 WBNB-USDT LP → VaultFlipToFlip에 예치하여 getReward() 자격 확보.
~$380 소액 예치
Step 1 — Flash Loan (이벤트 #15~#23)
8개 풀에서 총 $1.18B+ 플래시 론
7개 PCS Pair에서 총 2,323,376 WBNB, ForTube Bank에서 2,961,750 USDT를 차입.
CAKE/BNB: 1,051,687 | BUSD/BNB: 522,524 | SAFEMOON/BNB: 241,021
ETH/BNB: 210,158 | BTCB/BNB: 133,504 | BELT/BNB: 98,189 | DOT/BNB: 66,290
ForTube: 2,961,750 USDT
Step 2 — LP 주입 + 잔류 (#22~#28)
v2 Pool 유동성 추가, 144,445 LP 페어 컨트랙트에 잔류
7,744.59 WBNB + 2,961,750.45 USDT → PCS v2 WBNB-USDT Pool(0x16b9...)에 유동성 추가. 144,445.59 LP가 페어 컨트랙트 자체로 민팅됨(#26). 이 잔류 LP가 BunnyMinter의 removeLiquidity() 때 함께 소각되는 핵심 증폭기.
Mint #28: 2,961,750 USDT + 7,744.59 WBNB → 144,445.59 LP (to=Pair)
Step 3 — 가격 조작 (#29~#32, 핵심)
v1 Pool에서 대량 스왑으로 BNB 스팟 가격 $507→$1.65 붕괴
v1 Pool(0x20bc...)에서 2,315,631.95 WBNB → 3,826,047.62 USDT 스왑. 스왑 후 Sync #31: USDT 리저브 16,654 / WBNB 리저브 2,325,691. 실효환율 $1.65/BNB (정상 $507.09 대비 −99.7%).
Swap #32: 2,315,631.95 WBNB → 3,826,047.62 USDT ($1.65/BNB)
Step 4 — 보상 탈취 (#36~#81)
getReward() → BunnyMinter → 6,972,455.70 BUNNY 민팅
① VaultFlipToFlip → performanceFee(0.000156 LP) → BunnyMinter
② Burn #44: removeLiquidity()가 잔류 LP 144,445개까지 전부 소각 → 2,961,750 USDT + 7,744.59 WBNB 반환
③ Swap #51: ZapBSC가 조작된 v1 풀에서 2,961,750 USDT → 2,312,661 WBNB
④ Swap #57: 1,156,330 WBNB → 176,879 BUNNY (WBNB/BUNNY Pool)
⑤ Mint #65: 1,156,330 WBNB + 10,836 BUNNY → 105,257 BUNNY-BNB LP
⑥ LP #78 → BunnyPool 전달 (105,609 LP)
⑦ valueOfAsset(): 팽창된 WBNB 리저브(2,395,711) 기반 LP 가치 과대평가
⑧ Mint #80: 6,972,455.70 BUNNY 민팅 → VaultFlipToFlip → Attacker CA (#81)
6,972,455.699137 BUNNY 민팅 + 1,045,868 BUNNY (dev share → BunnyPool)
Step 5 — 이익 실현 (#88~#129)
BUNNY Dump → Flash Loan Repay → NET PROFIT
① Swap #91 (PancakeBunny WBNB/BUNNY): 4,880,718.99 BUNNY → 2,384,754.82 WBNB
② Swap #95 (PancakeSwap WBNB/BUNNY): 1,394,491.14 BUNNY → 56,270.43 WBNB
③ Swap #99 (v1 역스왑): 915,816.96 USDT → 3,059.69 WBNB
④ Swap #103 (v2 Pool): 141.41 WBNB → 53,889.19 USDT
⑤ ForTube 상환 (#104): 2,964,119.85 USDT (수수료 2,369.40)
⑥ 7개 PCS Pool 상환 (#108~#128): 수수료 포함 총 2,329,312 WBNB
⑦ #105: 697,245.57 BUNNY → Attacker EOA (0xa0acc6...)
⑧ #129: 114,631.54 WBNB → Attacker EOA
NET PROFIT: 114,631.54 WBNB × $507.09 = ~$58,132,000 + 697,245 BUNNY
2-3. Involved Entities & PnL
ATTACKER EOAExploiter
+114,631.54 WBNB + 697,245 BUNNY
ATTACKER CAExploit Contract (tx.to)
메인 공격 로직 실행
VICTIMVaultFlipToFlip (PancakeBunny)
getReward() 진입점
VULNERABLEBunnyMinterV2 + ZapBSC
LP 가격 계산 버그 소재지
FLASH LOAN ×7PancakeSwap Pair Pools
2,323,376 WBNB 차입/상환
FLASH LOANForTube Bank
2,961,750 USDT (fee: 2,369.40)
2-4. Oracle Manipulation Detail
정상 시세 (tokenPriceCache)
BNB$507.09
ETH$3,399
CAKE$27.02
⚠ v1 Pool After Swap #32
USDT 리저브16,654
WBNB 리저브2,325,691
실효 BNB 가격$1.65 (−99.7%)
LP 증폭기 (Burn #44)
잔류 LP 소각144,445.59
반환 USDT2,961,750.45
반환 WBNB7,744.59
BUNNY-BNB Pool (Sync #76)
WBNB 리저브2,395,711
BUNNY 리저브22,379
LP 가치극단적 과대평가
2-5. Key Events
| # | Event | From | To | Amount | Deviation |
| 1 | Swap (×7 PCS, Flashloan borrow) | PCS Pair Pools | Attacker CA | 2,323,376 WBNB | — |
| 2 | FlashLoan (#107 Flashloan borrow) | ForTube Bank | Attacker CA | 2,961,750.45 USDT | — |
| 3 | Mint LP (#28) | Attacker CA | PCS v2 WBNB-USDT | 7,744.59 WBNB + 2,961,750.45 USDT → 144,445.59 LP (잔류) | — |
| 4 | Swap #32 (v1 Price Crash) | Attacker CA | v1 WBNB-USDT | 2,315,631.95 WBNB → 3,826,047.62 USDT | $1.65/BNB −99.7% from $507.09 |
| 5 | Burn LP #44 | BunnyMinter | v2 Pool | 144,445.59 LP → 2,961,750 USDT + 7,744.59 WBNB | — |
| 6 | Swap #51 (조작 v1) | ZapBSC | v1 Pool | 2,961,750.45 USDT → 2,312,661.03 WBNB | $1.28/BNB −99.7% from $507 |
| 7 | Swap #57 | ZapBSC | WBNB/BUNNY | 1,156,330.51 WBNB → 176,879.22 BUNNY | — |
| 8 | Mint LP #65 + #77 | ZapBSC | BUNNY-BNB Pool | 2× (1,156,330 WBNB + BUNNY) → 105,609 LP | — |
| 9 | Mint BUNNY #80 | BunnyMinterV2 | Attacker CA | 6,972,455.70 BUNNY | — |
| 10 | Swap #91 (BUNNY dump 1) | Attacker CA | PancakeBunny WBNB/BUNNY | 4,880,718.99 BUNNY → 2,384,754.82 WBNB | 0.489 BNB/BUNNY ~$247/BUNNY |
| 11 | Swap #95 (BUNNY dump 2) | Attacker CA | PCS WBNB/BUNNY | 1,394,491.14 BUNNY → 56,270.43 WBNB | 0.040 BNB/BUNNY ~$20.5/BUNNY |
| 12 | Swap #99 (USDT→BNB) | Attacker CA | v1 Pool | 915,816.96 USDT → 3,059.69 WBNB | $299/BNB −41.0% from $507 |
| 13 | FlashLoan (Flashloan repayment) (#104) | Attacker CA | ForTube Bank | 2,964,119.85 USDT (fee: 2,369.40) | — |
| 14 | Swap (×7 PCS, Flashloan repayment) (#108~#128) | Attacker CA | PCS Pair Pools | ~2,329,312 WBNB (fee 포함) | — |
| 15 | Profit (#105+#129) | Attacker CA | Attacker EOA | 114,631.54 WBNB + 697,245.57 BUNNY | — |
2-6. 유사 공격 비교
| 프로토콜 | 날짜 | 체인 | 손실 | 공격 기법 |
| ★ | PancakeBunny | 2021-05-19 | BSC | ~$58M | LP Price Oracle + ×8 Flash Loan |
| AutoShark | 2021-05-24 | BSC | ~$820K | 동일 LP 가격 버그 (포크) |
| Merlin Labs | 2021-06-02 | BSC | ~$680K | 동일 LP 가격 버그 (포크) |
| PancakeHunny | 2021-06-03 | BSC | ~$200K | 동일 LP 가격 버그 (포크) |
| PolyBunny | 2021-07-16 | Polygon | ~$2.1M | 유사 보상 민팅 버그 |
| Warp Finance | 2020-12-17 | ETH | ~$7.7M | LP 가격 오라클 조작 |
2-7. Root Causes & Lessons
취약점
PriceCalculatorBSCV1.valueOfAsset()이 AMM 스팟 리저브를 오라클로 사용 — 플래시 론 조작에 완전 노출
UniswapV2Pair.burn()이 컨트랙트 전체 LP 잔고를 소각 — 공격자 주입 LP(144,445)까지 포함
amountBunnyToMint()의 5배 승수(bunnyPerProfitBNB=5e18)가 조작 값을 추가 증폭
v1/v2 풀 간 유동성 격차를 활용한 선택적 조작
교훈
Chainlink 등 외부 TWAP/오라클 사용 — AMM 스팟 기반 LP 가치 산정 폐지
balanceOf() 직접 사용 지양 — 내부 accounting 변수 관리
단일 Tx 민팅 상한선(cap) 설정
Flash Loan Guard — deposit↔getReward 사이 최소 블록 수 강제
2-8. 공격 당시 토큰 가격 (tokenPriceCache)
💡 가격 조작 핵심: v1 Pool에서 2,315,631 WBNB→3,826,047 USDT 스왑으로 BNB 스팟가 $507→$1.65 붕괴. 동시에 v2 Pool에 잔류시킨 144,445 LP가 BunnyMinter의 removeLiquidity() 시 함께 소각되어 2,961,750 USDT + 7,744 WBNB가 반환. 이 대량 토큰이 조작된 v1 풀을 경유하면서 BUNNY-BNB LP가 극단적으로 과대평가(WBNB 리저브 2,395,711 기준), 5배 승수까지 적용되어 6,972,455 BUNNY가 민팅됨. 정상 상태라면 0.000156 LP의 30% 수수료에 해당하는 미미한 보상만 발생.
3. 인터랙티브 Fund Flow
Step 1: Flash Loan
Step 2: LP 주입
Step 3: 가격 조작
Step 4: 보상 탈취
Step 5: Dump & Repay
7개 PCS Pair에서 2,323,376 WBNB + ForTube에서 2,961,750 USDT를 플래시 론으로 차입. 총 ~$1.18B.
4. BNB Balance Waterfall
Flash loan 유입유출BUNNY 매도 수익Net profit