1부에서 다룬 취약점은 모두 코드 라인 안에 원인이 있었습니다. 재진입이든 오버플로우든, 문제가 된 함수 자체에 결함이 있었죠. 그러나 2부에서 다루는 공격들은 성격이 다릅니다. 이들은 코드가 완벽해도 성립합니다. 각 함수는 명세대로 한 치의 오차도 없이 정확히 동작하는데, 그 함수들이 놓인 경제적 환경을 공격자가 조작하기 때문입니다. 여기서는 오라클 조작(플래시론 결합)과 MEV, 두 가지를 다룹니다.
스마트 컨트랙트는 온체인 데이터만 신뢰할 수 있습니다. 그런데 대출, 청산, 스테이블코인 같은 DeFi 프로토콜은 “ETH가 지금 얼마인가?” 같은 외부 가격을 반드시 알아야 합니다. 이 가격을 유동성이 얕은 단일 DEX의 현물 가격(spot price) 에서 가져오는 순간, 그 가격은 더 이상 객관적 사실이 아니라 조작 가능한 입력값이 됩니다. 유동성이 얕을수록 적은 자금으로도 가격을 크게 흔들 수 있기 때문입니다.
여기에 플래시론이 결합되면 파괴력이 극대화됩니다. 플래시론은 담보 없이 거대한 자금을 빌리되, 같은 트랜잭션 안에서 반드시 상환해야 한다는 조건이 붙은 대출입니다. 상환에 실패하면 트랜잭션 전체가 revert되어 원래 상태로 되돌아가므로, 대주(lender)는 원리금을 떼일 위험이 전혀 없습니다. 공격자 입장에서 이는 자기 자본이 거의 없이도 순간적으로 수백만 달러를 운용할 수 있다는 뜻입니다.
이 모든 과정은 하나의 원자적(atomic) 트랜잭션 안에서 일어납니다.
// 취약: 단일 DEX 의 즉석 가격에 의존
function getPrice() public view returns (uint) {
// reserve0, reserve1 은 순간적으로 조작 가능하다
return reserve1 * 1e18 / reserve0;
}
function borrow(uint collateralAmount) public {
uint price = getPrice(); // ← 조작된 가격
uint borrowable = collateralAmount * price; // 부풀려진 담보 가치
// ...과도한 대출 실행
} 2020년 bZx, Harvest Finance 등이 이 패턴으로 연쇄 피해를 입었습니다. bZx는 여러 프로토콜을 엮은 플래시론 공격으로 초기에 수십만 달러 규모의 손실을 봤고, 이후 추가 공격으로 피해가 누적되었습니다. Harvest Finance는 스테이블코인 풀의 가격을 왜곡하는 방식으로 약 3,400만 달러를 잃었습니다. 이 사건들은 업계에 “플래시론은 그 자체로 취약점이 아니라 증폭기(amplifier)“라는 인식을 확산시켰습니다. 근본 원인은 어디까지나 조작 가능한 오라클이며, 플래시론은 공격에 필요한 자본의 문턱을 사실상 0으로 낮춰줄 뿐입니다.
// 개선: Chainlink 피드 + 신선도(staleness) 검사
AggregatorV3Interface internal feed;
function getPrice() public view returns (uint) {
(, int256 answer, , uint256 updatedAt, ) = feed.latestRoundData();
require(answer > 0, "invalid price");
require(block.timestamp - updatedAt < 3600, "stale price"); // 1시간 이상 지난 값 거부
return uint256(answer);
} 이더리움의 멤풀(mempool)은 공개되어 있습니다. 아직 블록에 포함되지 않은 대기 중인 트랜잭션을 누구나 들여다볼 수 있고, 검증자(validator)는 자신이 만드는 블록 안에서 트랜잭션의 순서를 결정할 권한을 가집니다. 이 두 성질이 결합되면, 트랜잭션 순서를 조작해 이익을 뽑아내는 MEV가 발생합니다. MEV는 특정 컨트랙트의 버그가 아니라 공개 블록체인의 구조에서 비롯되는 성질이지만, 최종 사용자에게는 실질적인 금전 손실로 나타납니다.
피해자의 거래는 코드상 정확히 명세대로 실행되었습니다. 그러나 앞뒤로 끼워진 두 거래 때문에 결과적으로 더 나쁜 가격을 받게 된 것입니다. MEV에는 이 샌드위치 외에도 청산 경쟁, 아비트리지, 백런 등 다양한 형태가 포함됩니다.
amountOutMin을 타이트하게 설정해, 조작으로 가격이 크게 나빠지면 거래 자체가 revert되게 합니다. 사용자가 직접 걸 수 있는 1차 방어선입니다.// 사용자 측 방어: 슬리피지 보호가 있는 스왑 호출
router.swapExactTokensForTokens(
amountIn,
amountOutMin, // ← 최소 수령량. 이보다 나쁘면 revert
path,
msg.sender,
block.timestamp + 300
); | # | 공격 | 조작 대상 | 대표 사례 | 핵심 방어 |
|---|---|---|---|---|
| 5 | 오라클 조작 / 플래시론 | 가격 오라클 | bZx, Harvest | TWAP · 탈중앙 오라클 |
| 6 | MEV / 프론트러닝 | 트랜잭션 순서 | 샌드위치 공격 | 슬리피지 · 프라이빗 멤풀 |
두 공격의 공통점은, 개별 함수는 결백하다는 것입니다. 취약한 것은 그 함수들이 신뢰한 입력(가격)과 그 함수들이 실행된 환경(공개 멤풀)입니다. 이는 스마트 컨트랙트 보안이 단순한 코드 검수를 넘어, 경제적 인센티브 설계의 영역으로 확장되어야 함을 분명히 보여줍니다.
다음 3부에서는 한 층 더 아래로 내려가, 블록체인의 토대 그 자체인 합의(consensus) 레벨 공격과 접근 제어 실패를 다룹니다. 51% 공격과, 무려 5억 달러 이상을 영구 동결시킨 Parity 사건이 등장합니다.
이 글은 ChainLab 기술 시리즈의 일부입니다.
Tags: 블록체인보안, 오라클문제, 플래시론, MEV, DeFi
중고거래 안전결제, 다들 써보셨죠? AI 결제에도 이게 필요합니다. 문제는, 생각보다 훨씬 까다롭다는 거예요. 중고거래를 떠올려…
앞 편의 x402가 자판기였다면, 이번 두 방식은 '용돈 한도'와 '술집 외상장부'에 가깝습니다. 앞 편 복습:…