2M 스캔/일을 처리하는 Honeypot Scanner 구축 ($0)

발행: (2026년 2월 1일 오전 07:23 GMT+9)
10 분 소요
원문: Dev.to

Source: Dev.to

(위에 제공된 텍스트 외에 번역할 내용이 없습니다. 번역하고 싶은 본문을 알려주시면 도와드리겠습니다.)

The Problem: Honeypot Tokens

허니팟 토큰은 구매는 가능하지만 판매를 차단하는 사기 스마트 계약입니다. 사기꾼은 Solidity에서 tx.originmsg.sender의 차이를 이용합니다:

// Malicious code example
function transfer(address to, uint256 amount) public returns (bool) {
    require(tx.origin == msg.sender, "No DEX sells allowed");
    // Transfer logic...
}
  • 직접 구매tx.origin == msg.sender
  • Uniswap을 통한 판매tx.origin != msg.sender

거래가 되돌려지고 자금은 영원히 묶이게 됩니다.

Architecture Overview

┌─────────────────┐
│   Next.js 16    │  Frontend (Cloudflare Pages)
│   React 19      │
└────────┬────────┘


┌─────────────────┐
│ Cloudflare      │  Edge API (300+ locations)
│ Workers         │  - Input validation
│                 │  - Pattern detection
│                 │  - Response caching
└────────┬────────┘


┌─────────────────┐
│ Cloudflare KV   │  Global cache (24 h TTL)
│                 │  95 % hit rate
└────────┬────────┘


┌─────────────────┐
│ Etherscan API   │  Source‑code retrieval
│ (6 keys)        │  Rotation for rate limits
└─────────────────┘

왜 Cloudflare Workers + KV?

  1. Edge Computing = 일관된 지연 시간
    Workers는 전 세계 300개 이상의 엣지 위치에서 실행됩니다. 도쿄에 있든 런던에 있든 약 2 초의 응답 시간을 얻을 수 있습니다—콜드 스타트도 없고, 지역 병목 현상도 없습니다.

  2. KV Caching = 막대한 비용 절감
    스마트 계약은 배포 후 변경할 수 없으므로 공격적인 캐싱이 안전합니다:

// Check cache first
const cached = await env.HONEYPOT_CACHE.get(address);
if (cached) {
  return JSON.parse(cached);
}

// Fetch from Etherscan
const sourceCode = await fetchFromEtherscan(address);

// Cache for 24 h
await env.HONEYPOT_CACHE.put(
  address,
  JSON.stringify(result),
  { expirationTtl: 86400 }
);

95 % 캐시 적중률을 기준으로 다음과 같은 결과를 얻습니다:

  • 하루 100 k Worker 요청 (무료 티어)
  • 하루 100 k KV 읽기 (무료 티어)

≈ 2 M 잠재 스캔/일$0 / 월

  1. 내장 DDoS 보호
    Cloudflare의 엣지 네트워크가 DDoS 공격을 자동으로 완화합니다. 누군가 API를 스팸하려고 시도했을 때, 로그를 확인하기 전까지는 전혀 눈치채지 못했습니다.

탐지 알고리즘

패턴 기반 정적 분석

13개의 정규식 패턴을 사용해 허니팟 기법을 찾습니다:

const patterns = [
  // Core ERC20 abuse
  /function\s+balanceOf[^}]*tx\.origin/,
  /function\s+allowance[^}]*tx\.origin/,
  /function\s+transfer[^}]*tx\.origin/,

  // Hidden helpers
  /function\s+_taxPayer[^}]*tx\.origin/,
  /function\s+_isSuper[^}]*tx\.origin/,

  // Auth bypasses
  /require\s*\([^)]*tx\.origin/,
  /if\s*\([^)]*tx\.origin[^)]*==|!=/,
  /assert\s*\([^)]*tx\.origin/,
  /\[tx\.origin\]/,

  // Transfer blocks
  /_isSuper\s*\(\s*recipient\s*\)/,
  /_canTransfer[^}]*return\s+false/,
  /require\s*\([^)]*_whitelisted\[.*\]\s*&&\s*_whitelisted\[/,
  /if\s*\([^)]*isPair\[.*\][^}]*\)\s*{\s*taxAmount\s*=.*\*\s*9[5-9]/
];

신뢰도 점수 매기기

const patternCount = patterns.filter(p => p.test(sourceCode)).length;

if (patternCount >= 2) {
  return { isHoneypot: true, confidence: 95 };
} else if (patternCount === 1) {
  return { isHoneypot: false, confidence: 50, warning: "Suspicious" };
} else {
  return { isHoneypot: false, confidence: 100 };
}

왜 임계값을 2로 설정했나요?

  • 실제 허니팟은 보통 3‑7개의 패턴을 나타냅니다.
  • 정상적인 계약은 > 1개의 패턴을 거의 보여주지 않습니다.
  • 이렇게 하면 **≈ 98 %**의 민감도를 유지하면서 오탐을 최소화합니다.

구현 세부 사항

입력 검증

EIP‑55 체크섬 검증을 keccak256을 사용하여 수행합니다:

import { keccak256 } from '@noble/hashes/sha3';
import { bytesToHex } from '@noble/hashes/utils';

function isValidChecksum(address: string): boolean {
  const addr = address.slice(2).toLowerCase();
  const hash = bytesToHex(keccak256(addr));

  for (let i = 0; i = 8 && addr[i] !== addr[i].toUpperCase()) return false;
    if (hashChar  controller.abort(), 10_000);
}

타임아웃이 있는 Fetch

const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 10_000);

try {
  const response = await fetch(url, { signal: controller.signal });
  // Process response…
} catch (error) {
  if (error.name === 'AbortError') {
    throw new Error('Request timeout');
  }
  throw error;
} finally {
  clearTimeout(timeoutId);
}

코드 정리

패턴 매칭 전에 주석을 제거하고 공백을 정규화합니다:

function sanitizeCode(code: string): string {
  return code
    .replace(/\/\*[\s\S]*?\*\//g, '') // Block comments
    .replace(/\/\/.*/g, '')            // Line comments
    .replace(/\s+/g, ' ')             // Collapse whitespace
    .trim();
}

최종 생각

edge computing, global KV caching, 그리고 경량 정적‑분석 엔진을 활용함으로써, HoneypotScan은 하루에 수백만 건의 스캔을 비용 없이 안전하게 처리할 수 있습니다. 동일한 패턴은 대규모로 운영해야 하지만 예산이 없는 모든 온‑체인 보안‑검사 서비스에 적용될 수 있습니다.

보안 기능

CORS 화이트리스트

const ALLOWED_ORIGINS = [
  'https://honeypotscan.pages.dev',
  'https://www.honeypotscan.com',
  'http://localhost:3000',
];

function handleCORS(request: Request): Response | null {
  const origin = request.headers.get('Origin');
  if (origin && !ALLOWED_ORIGINS.includes(origin)) {
    return new Response('Forbidden', { status: 403 });
  }
  return null;
}

콘텐츠 보안 정책

const CSP = [
  "default-src 'self'",
  "script-src 'self' 'unsafe-inline' 'unsafe-eval'",
  "style-src 'self' 'unsafe-inline'",
  "connect-src 'self' https://honeypotscan-api.teycircoder4.workers.dev",
  "frame-ancestors 'none'",
].join('; ');

response.headers.set('Content-Security-Policy', CSP);

속도 제한

메모리 기반 간단한 속도 제한 (매분 초기화):

const rateLimits = new Map();

function checkRateLimit(ip: string): boolean {
  const count = rateLimits.get(ip) || 0;
  if (count >= 30) return false;

  rateLimits.set(ip, count + 1);
  return true;
}

프론트엔드 기능

URL 해시를 통한 결과 공유

function shareResult(result: ScanResult) {
  const encoded = btoa(JSON.stringify(result));
  const url = `${window.location.origin}#result=${encoded}`;
  navigator.clipboard.writeText(url);
}

// On page load
const hash = window.location.hash;
if (hash.startsWith('#result=')) {
  const encoded = hash.slice(8);
  const result = JSON.parse(atob(encoded));
  displayResult(result);
}

로컬 스캔 기록

마지막 10개의 스캔이 localStorage에 저장됩니다:

function saveToHistory(result: ScanResult) {
  const history = JSON.parse(localStorage.getItem('scanHistory') || '[]');
  history.unshift(result);
  history.splice(10); // Keep only last 10
  localStorage.setItem('scanHistory', JSON.stringify(history));
}

JSON으로 내보내기

function exportResult(result: ScanResult) {
  const data = {
    scanner: 'HoneypotScan',
    version: '1.0',
    scannedAt: new Date().toISOString(),
    result,
  };

  const blob = new Blob([JSON.stringify(data, null, 2)], {
    type: 'application/json',
  });

  const url = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url;
  a.download = `honeypot-scan-${result.address}.json`;
  a.click();
}

성능 최적화

병렬 패턴 매칭

const matches = await Promise.all(
  patterns.map(async (pattern) => ({
    pattern: pattern.name,
    matched: pattern.regex.test(sourceCode),
  }))
);

캐시 히트 시 조기 종료

// Check cache before any processing
const cached = await env.HONEYPOT_CACHE.get(address);
if (cached) {
  return new Response(cached, {
    headers: { 'Content-Type': 'application/json' },
  });
}

지연 로딩 컴포넌트

const ScanHistory = dynamic(() => import('./ScanHistory'), {
  ssr: false,
  loading: () => ,
});

배포

Cloudflare Workers

# Install Wrangler CLI
npm install -g wrangler

# Login to Cloudflare
wrangler login

# Deploy
wrangler deploy

환경 변수

# wrangler.toml
name = "honeypotscan-api"
main = "src/worker.ts"
compatibility_date = "2024-01-01"

[[kv_namespaces]]
binding = "HONEYPOT_CACHE"
id = "your-kv-namespace-id"

[vars]
ETHERSCAN_API_KEY_1 = "your-key-1"
ETHERSCAN_API_KEY_2 = "your-key-2"
# ... more keys

Cloudflare Pages

# Build Next.js app
npm run build

# Deploy to Pages
npx wrangler pages deploy out

교훈

잘된 점

  • KV 캐싱은 마법 – 95 % 적중률 = 막대한 비용 절감
  • 엣지 컴퓨팅은 지연 문제를 없앰 – 전 세계적으로 일관된 ~2 s 응답 시간
  • 패턴 기반 탐지는 빠름 – 정규식 매칭이 < 100 ms 소요
  • 불변 계약 = 적극적인 캐싱 – 캐시 무효화가 필요 없음

주의할 점

  • KV 최종 일관성 – 쓰기가 전 세계에 전파되는 데 ~60 s 소요
  • 10 ms CPU 제한 – 정규식 패턴을 최적화해야 함
  • WebSocket 지원 없음 – 실시간 업데이트 불가
  • 첫 배포 시 콜드 스타트 – 전 세계 전파에 ~30 s 소요

다르게 할 점

  • 패턴 매칭 속도를 높이기 위해 WebAssembly 추가
  • 새로운 패턴 탐지를 위한 머신러닝 구현
  • 시간이 지남에 따라 패턴을 개선하는 피드백 루프 구축
  • 더 많은 체인 지원 추가 (BSC, Avalanche 등)

결과

  • 평균 2 s 응답 시간
  • 95 % 캐시 적중률
  • 월 $0 인프라 비용
  • 무료 티어에서 일일 2 M 스캔 용량
  • 민감도 98 %, 특이도 97 %

직접 해보세요

전체 스택은 오픈 소스입니다. 자유롭게 포크하고, 수정하거나, 자체 엣지‑컴퓨팅 프로젝트의 참고 자료로 사용하세요.

결론

  • 읽기 위주, 쓰기 적은 워크로드
  • 전 세계 저지연 요구사항
  • 무료로 시작해 확장해야 하는 프로젝트
  • 불변 데이터(적극적인 캐싱)

HoneypotScan에 있어서는 이상적인 아키텍처였습니다: 빠르고, 무료이며, 높은 확장성을 가짐.

질문이 있나요? 댓글에 남겨 주세요! 👇

Back to Blog

관련 글

더 보기 »