פיתוח מערכת התרעה על הונאות אישור טוקנים

אנו מפתחים מערכת התרעה על הונאות אישור המגנה על הנכסים שלך לפני חתימת העסקה. אישור טוקנים הוא אחת הפעולות המסוכנות ביותר ב-Web3 – משתמש נותן לחוזה את הזכות להוציא את הטוקנים שלו ללא מעורבות עתידית. הונאות אישור הן הגורם המוביל לאובדן נכסים

שירותי פיתוח בלוקצ'יין

שאלות נפוצות

העבודות האחרונות

  • image_website-b2b-advance_0.webp
    פיתוח אתר חברה B2B ADVANCE
    1450
  • image_web-applications_feedme_466_0.webp
    פיתוח אפליקציית ווב עבור FEEDME
    1308
  • image_websites_belfingroup_462_0.webp
    פיתוח אתר עבור BELFINGROUP
    1003
  • image_ecommerce_furnoro_435_0.webp
    פיתוח חנות מקוונת לחברת FURNORO
    1269
  • image_logo-advance_0.webp
    עיצוב לוגו לחברת B2B Advance
    717
  • image_crm_enviok_479_0.webp
    פיתוח אפליקציית ווב עבור Enviok
    1008

אנו מפתחים מערכת התרעה מפני הונאות אישור (approval scams) המגנה על הנכסים שלך לפני חתימת עסקה. אישור טוקנים (Token Approval) הוא אחת הפעולות המסוכנות ביותר ב-Web3 — משתמש מעניק לחוזה את הזכות להוציא את הטוקנים שלו ללא מעורבות עתידית שלו. הונאות אישור הן הגורם המוביל לגניבת נכסים: לפי Revoke.cash, ההפסדים עלו על 2.8 מיליארד דולר. מערכת ההתרעה שלנו מזהה אישורים חשודים פי 10 מהר יותר מבדיקות ידניות, מנתחת בקשות ממתינות ומנטרת אישורים שהונפקו באמצעות סימולציה ומאגרי כתובות. עם ניסיון של למעלה מ-5 שנים באבטחת Web3, אנו בונים הגנה שמונעת גניבה לפני שהיא מתרחשת.

מדוע הונאות אישור הן האיום הגדול ביותר על הארנק שלך

ERC-20 approve: interface ApprovalAnalysis { isSuspicious: boolean; riskScore: number; // 0-100 riskFactors: string[]; simulatedStateChanges: StateChange[]; spenderInfo: SpenderInfo; } interface SpenderInfo { address: string; isVerified: boolean; // есть ли в whitelist известных dApp isNewContract: boolean; // контракт < 30 дней hasSourceCode: boolean; // верифицирован на Etherscan blacklisted: boolean; // в списке известных scammers } async function analyzeApproval( txParams: TransactionParams, chainId: number ): Promise<ApprovalAnalysis> { const riskFactors: string[] = []; let riskScore = 0; // 1. Симуляция транзакции const simulation = await simulateTransaction(txParams, chainId); // Извлекаем approve вызовы из simulation const approvals = extractApprovals(simulation.stateChanges); for (const approval of approvals) { // 2. Проверка типа approval if (approval.type === "setApprovalForAll") { riskFactors.push("SET_APPROVAL_FOR_ALL — передаёт права на все NFT коллекции"); riskScore += 40; } if (approval.amount === MaxUint256) { riskFactors.push("UNLIMITED_APPROVAL — безлимитный апрувал токена"); riskScore += 20; } // 3. Анализ spender контракта const spenderInfo = await analyzeSpender(approval.spender, chainId); if (spenderInfo.blacklisted) { riskFactors.push("KNOWN_SCAMMER — адрес в чёрном списке"); riskScore += 60; } if (spenderInfo.isNewContract) { riskFactors.push("NEW_CONTRACT — контракт задеплоен менее 30 дней назад"); riskScore += 25; } if (!spenderInfo.hasSourceCode) { riskFactors.push("UNVERIFIED_CONTRACT — исходный код не верифицирован"); riskScore += 15; } if (!spenderInfo.isVerified && !spenderInfo.hasSourceCode) { riskScore += 20; // дополнительный штраф за полную непрозрачность } } return { isSuspicious: riskScore >= 50, riskScore: Math.min(100, riskScore), riskFactors, simulatedStateChanges: simulation.stateChanges, spenderInfo: approvals[0]?.spender ? await analyzeSpender(approvals[0].spender, chainId) : null }; } מאפשר למוציא (spender) להעביר עד // Whitelist известных dApp контрактов const KNOWN_SAFE_SPENDERS: Record<number, Set<string>> = { 1: new Set([ // Ethereum mainnet "0x000000000022d473030f116ddee9f6b43ac78ba3", // Permit2 (Uniswap) "0x68b3465833fb72a70ecdf485e0e4c7bd8665fc45", // Uniswap Universal Router "0x7a250d5630b4cf539739df2c5dacb4c659f2488d", // Uniswap V2 Router "0xe592427a0aece92de3edee1f18e0157c05861564", // Uniswap V3 Router "0x1111111254eeb25477b68fb85ed929f73a960582", // 1inch V5 "0x00000000219ab540356cbb839cbe05303d7705fa", // ETH2 Deposit Contract ]), // Arbitrum, Base, Polygon... }; // Blacklist известных scam адресов // Источники: Forta, Chainabuse, Revoke.cash, MobyMask const KNOWN_SCAM_SPENDERS: Record<number, Set<string>> = { 1: new Set([ // Обновляется из Forta feeds и community reports ]) }; async function analyzeSpender( spenderAddress: string, chainId: number ): Promise<SpenderInfo> { const normalizedAddress = spenderAddress.toLowerCase(); // Проверка whitelist const isVerified = KNOWN_SAFE_SPENDERS[chainId]?.has(normalizedAddress) ?? false; // Проверка blacklist const blacklisted = KNOWN_SCAM_SPENDERS[chainId]?.has(normalizedAddress) ?? false; // Проверка возраста контракта const deployBlock = await getContractDeployBlock(spenderAddress, chainId); const currentBlock = await getCurrentBlock(chainId); const blockAge = currentBlock - deployBlock; const isNewContract = blockAge < 200_000; // ~30 дней на Ethereum // Проверка верифицированности на Etherscan const hasSourceCode = await checkEtherscanVerification(spenderAddress, chainId); return { address: spenderAddress, isVerified, blacklisted, isNewContract, hasSourceCode }; } טוקנים. ERC-721/ERC-1155 interface ApprovalRecord { owner: string; spender: string; tokenAddress: string; tokenType: "ERC20" | "ERC721" | "ERC1155"; amount: bigint | "unlimited" | "all"; // для ERC-20 / setApprovalForAll blockNumber: number; txHash: string; timestamp: number; revoked: boolean; } // Слушаем Approval и ApprovalForAll события async function indexApprovals( provider: ethers.Provider, userAddress: string ): Promise<ApprovalRecord[]> { // ERC-20 Approval(owner, spender, value) const erc20ApprovalFilter = { topics: [ ethers.id("Approval(address,address,uint256)"), ethers.zeroPadValue(userAddress, 32) // owner = userAddress ] }; // ERC-721/1155 ApprovalForAll(owner, operator, approved) const approvalForAllFilter = { topics: [ ethers.id("ApprovalForAll(address,address,bool)"), ethers.zeroPadValue(userAddress, 32) ] }; const [erc20Logs, nftLogs] = await Promise.all([ provider.getLogs({ ...erc20ApprovalFilter, fromBlock: 0, toBlock: "latest" }), provider.getLogs({ ...approvalForAllFilter, fromBlock: 0, toBlock: "latest" }) ]); return parseApprovalLogs([...erc20Logs, ...nftLogs]); } מעניק זכויות לכל ה-NFTs — הצורה המסוכנת ביותר. Permit (EIP-2612) מאפשר חתימות אישור ללא גז (gasless) ללא עסקאות on-chain; תוקף יכול לשלוח async function monitorApprovalUsage( approval: ApprovalRecord, provider: ethers.Provider ): Promise<void> { const transferFilter = { address: approval.tokenAddress, topics: [ ethers.id("Transfer(address,address,uint256)"), ethers.zeroPadValue(approval.owner, 32) // from = owner ] }; // Подписываемся на Transfer события от owner через spender provider.on(transferFilter, async (log) => { const tx = await provider.getTransaction(log.transactionHash); // Транзакцию отправил spender (не owner) — это использование approval if (tx.from.toLowerCase() === approval.spender.toLowerCase()) { const transferAmount = BigInt(log.data); await sendAlert({ type: "APPROVAL_USED", severity: "HIGH", owner: approval.owner, spender: approval.spender, amount: transferAmount, txHash: log.transactionHash, message: `Ваш апрувал используется! Контракт ${approval.spender} ` + `переводит ${formatAmount(transferAmount)} токенов с вашего адреса.` }); } }); } מאוחר יותר, בחשאי. מערכת ההתרעה שלנו מנתחת עסקאות תוך 1-2 שניות עם דיוק זיהוי של מעל 99%.

אילו סוגי אישורים דורשים תשומת לב מיוחדת?

סוג זכויות סיכון דוגמת הגנה
ERC-20 approve עד כמות הטוקנים בינוני סימולציה + הגבלה
setApprovalForAll כל ה-NFTs בקולקציה גבוה בדיקה חובה
חתימת Permit2 בלתי מוגבל דרך off-chain קריטי ניטור עסקאות חתימה
אישור אינסופי MaxUint256 גבוה התראה על אישור ממתין

כיצד פועלת מערכת ההתרעה על אישורים חשודים

המערכת משתמשת בשתי שכבות: סינון לפני עסקה (ניתוח עסקאות ממתינות לפני חתימה) וניטור לאחר אישור (מעקב אחר אישורים שהונפקו). ציון הסיכון מחושב על ידי אלגוריתם המתחשב בסוג האישור, נתוני המוציא וגיל החוזה. אם הציון עולה על 70, המערכת חוסמת את החתימה.

ניתוח עסקאות ממתינות — פיתוח מערכת ההתרעה

סימולציה באמצעות Tenderly או Alchemy

לפני החתימה, אנו מדמים את העסקה ומנתחים שינויי מצב. פונקציית קוד:

interface ApprovalAnalysis { isSuspicious: boolean; riskScore: number; // 0-100 riskFactors: string[]; simulatedStateChanges: StateChange[]; spenderInfo: SpenderInfo; } interface SpenderInfo { address: string; isVerified: boolean; // есть ли в whitelist известных dApp isNewContract: boolean; // контракт < 30 дней hasSourceCode: boolean; // верифицирован на Etherscan blacklisted: boolean; // в списке известных scammers } async function analyzeApproval( txParams: TransactionParams, chainId: number ): Promise<ApprovalAnalysis> { const riskFactors: string[] = []; let riskScore = 0; // 1. Симуляция транзакции const simulation = await simulateTransaction(txParams, chainId); // Извлекаем approve вызовы из simulation const approvals = extractApprovals(simulation.stateChanges); for (const approval of approvals) { // 2. Проверка типа approval if (approval.type === "setApprovalForAll") { riskFactors.push("SET_APPROVAL_FOR_ALL — передаёт права на все NFT коллекции"); riskScore += 40; } if (approval.amount === MaxUint256) { riskFactors.push("UNLIMITED_APPROVAL — безлимитный апрувал токена"); riskScore += 20; } // 3. Анализ spender контракта const spenderInfo = await analyzeSpender(approval.spender, chainId); if (spenderInfo.blacklisted) { riskFactors.push("KNOWN_SCAMMER — адрес в чёрном списке"); riskScore += 60; } if (spenderInfo.isNewContract) { riskFactors.push("NEW_CONTRACT — контракт задеплоен менее 30 дней назад"); riskScore += 25; } if (!spenderInfo.hasSourceCode) { riskFactors.push("UNVERIFIED_CONTRACT — исходный код не верифицирован"); riskScore += 15; } if (!spenderInfo.isVerified && !spenderInfo.hasSourceCode) { riskScore += 20; // дополнительный штраф за полную непрозрачность } } return { isSuspicious: riskScore >= 50, riskScore: Math.min(100, riskScore), riskFactors, simulatedStateChanges: simulation.stateChanges, spenderInfo: approvals[0]?.spender ? await analyzeSpender(approvals[0].spender, chainId) : null }; } 

מאגר כתובות מוציאים ידועות

// Whitelist известных dApp контрактов const KNOWN_SAFE_SPENDERS: Record<number, Set<string>> = { 1: new Set([ // Ethereum mainnet "0x000000000022d473030f116ddee9f6b43ac78ba3", // Permit2 (Uniswap) "0x68b3465833fb72a70ecdf485e0e4c7bd8665fc45", // Uniswap Universal Router "0x7a250d5630b4cf539739df2c5dacb4c659f2488d", // Uniswap V2 Router "0xe592427a0aece92de3edee1f18e0157c05861564", // Uniswap V3 Router "0x1111111254eeb25477b68fb85ed929f73a960582", // 1inch V5 "0x00000000219ab540356cbb839cbe05303d7705fa", // ETH2 Deposit Contract ]), // Arbitrum, Base, Polygon... }; // Blacklist известных scam адресов // Источники: Forta, Chainabuse, Revoke.cash, MobyMask const KNOWN_SCAM_SPENDERS: Record<number, Set<string>> = { 1: new Set([ // Обновляется из Forta feeds и community reports ]) }; async function analyzeSpender( spenderAddress: string, chainId: number ): Promise<SpenderInfo> { const normalizedAddress = spenderAddress.toLowerCase(); // Проверка whitelist const isVerified = KNOWN_SAFE_SPENDERS[chainId]?.has(normalizedAddress) ?? false; // Проверка blacklist const blacklisted = KNOWN_SCAM_SPENDERS[chainId]?.has(normalizedAddress) ?? false; // Проверка возраста контракта const deployBlock = await getContractDeployBlock(spenderAddress, chainId); const currentBlock = await getCurrentBlock(chainId); const blockAge = currentBlock - deployBlock; const isNewContract = blockAge < 200_000; // ~30 дней на Ethereum // Проверка верифицированности на Etherscan const hasSourceCode = await checkEtherscanVerification(spenderAddress, chainId); return { address: spenderAddress, isVerified, blacklisted, isNewContract, hasSourceCode }; } 

ניטור אישורים שהונפקו

אינדקסר של אישורים מאושרים

interface ApprovalRecord { owner: string; spender: string; tokenAddress: string; tokenType: "ERC20" | "ERC721" | "ERC1155"; amount: bigint | "unlimited" | "all"; // для ERC-20 / setApprovalForAll blockNumber: number; txHash: string; timestamp: number; revoked: boolean; } // Слушаем Approval и ApprovalForAll события async function indexApprovals( provider: ethers.Provider, userAddress: string ): Promise<ApprovalRecord[]> { // ERC-20 Approval(owner, spender, value) const erc20ApprovalFilter = { topics: [ ethers.id("Approval(address,address,uint256)"), ethers.zeroPadValue(userAddress, 32) // owner = userAddress ] }; // ERC-721/1155 ApprovalForAll(owner, operator, approved) const approvalForAllFilter = { topics: [ ethers.id("ApprovalForAll(address,address,bool)"), ethers.zeroPadValue(userAddress, 32) ] }; const [erc20Logs, nftLogs] = await Promise.all([ provider.getLogs({ ...erc20ApprovalFilter, fromBlock: 0, toBlock: "latest" }), provider.getLogs({ ...approvalForAllFilter, fromBlock: 0, toBlock: "latest" }) ]); return parseApprovalLogs([...erc20Logs, ...nftLogs]); } 

התראה על שימוש באישור

הערה: כאשר נעשה שימוש באישור שהונפק, עלינו להבחין בין פעולות לגיטימיות לפעולות חריגות. האלגוריתם מופעל אם ההעברה יזומה על ידי המוציא (לא הבעלים).

async function monitorApprovalUsage( approval: ApprovalRecord, provider: ethers.Provider ): Promise<void> { const transferFilter = { address: approval.tokenAddress, topics: [ ethers.id("Transfer(address,address,uint256)"), ethers.zeroPadValue(approval.owner, 32) // from = owner ] }; // Подписываемся на Transfer события от owner через spender provider.on(transferFilter, async (log) => { const tx = await provider.getTransaction(log.transactionHash); // Транзакцию отправил spender (не owner) — это использование approval if (tx.from.toLowerCase() === approval.spender.toLowerCase()) { const transferAmount = BigInt(log.data); await sendAlert({ type: "APPROVAL_USED", severity: "HIGH", owner: approval.owner, spender: approval.spender, amount: transferAmount, txHash: log.transactionHash, message: `Ваш апрувал используется! Контракт ${approval.spender} ` + `переводит ${formatAmount(transferAmount)} токенов с вашего адреса.` }); } }); } 

מאפייני Permit2

Uniswap Permit2 דורש const PERMIT2_TRANSFER_FROM_SELECTOR = "0x36c78516"; function isPermit2Transfer(calldata: string): boolean { return calldata.startsWith(PERMIT2_TRANSFER_FROM_SELECTOR); } function decodePermit2Transfer(calldata: string): { token: string; from: string; to: string; amount: bigint; } { const iface = new ethers.Interface(PERMIT2_ABI); const decoded = iface.decodeFunctionData("transferFrom", calldata); return { token: decoded.token, from: decoded.from, to: decoded.to, amount: decoded.amount }; } יחיד עבור חוזה Permit2. פרוטוקולים אחרים משתמשים בו עם הרשאות מבוססות חתימה. המערכת מזהה דפוס זה:

const PERMIT2_TRANSFER_FROM_SELECTOR = "0x36c78516"; function isPermit2Transfer(calldata: string): boolean { return calldata.startsWith(PERMIT2_TRANSFER_FROM_SELECTOR); } function decodePermit2Transfer(calldata: string): { token: string; from: string; to: string; amount: bigint; } { const iface = new ethers.Interface(PERMIT2_ABI); const decoded = iface.decodeFunctionData("transferFrom", calldata); return { token: decoded.token, from: decoded.from, to: decoded.to, amount: decoded.amount }; } 

שילוב בארנק או ב-dApp

המערכת מוטמעת דרך wallet_watchAsset או תוסף דפדפן. MetaMask Snaps מספק גישה ל-hook של onTransaction.

ערוץ יישום זמן השהיה
Hook של ספק הארנק סינון לפני חתימה ב-MetaMask Snaps < 1 שנייה
תוסף דפדפן סינון כל עסקאות ה-dApp < 2 שניות
שילוב UI ב-dApp SDK בצד ה-dApp < 1 שנייה
התראת אימייל/טלגרם ניטור לאחר אישור בזמן אמת

דוגמה: משתמש מבקר באתר פישינג המבקש אישור עבור חוזה שנפרס לפני שעתיים, עם קוד לא מאומת וסכום של MaxUint256. המערכת מדרגת את הסיכון ב-95 וחוסמת את החתימה.

כיצד השילוב מגן מפני התקפות Permit2

Permit2 מאפשר שימוש בחתימה אחת למספר בלתי מוגבל של העברות. תוקף יכול להשיג את החתימה באמצעות פישינג ולשלוח permit() מאוחר יותר. המערכת מזהה חתימות כאלה בסינון המוקדם ועוקבת אחר השימוש בהן.

כיצד לשלב את המערכת: מדריך שלב-אחר-שלב

  1. התקן את MetaMask Snap או תוסף דפדפן.
  2. חבר API לסימולציה (Tenderly/Alchemy) — הסינון יפעל מיד.
  3. הגדר רשימת היתרים/חסימות — הוסף dApps ידועים וכתובות הונאה.
  4. התחל לנטר אישורים שהונפקו באמצעות אינדקסר אירועים.
  5. הגדר ערוצי התראה (אימייל, טלגרם, webhook).
רשימת בדיקה לאישור בטוח- בדוק תמיד את כתובת המוציא ב-Etherscan. - הגבל את סכום האישור אם אפשר. - השתמש במערכת שלנו לסינון אוטומטי לפני חתימה.

חיסכון מהטמעה: מניעת התקפה אחת יכולה לחסוך בין $10,000 ל-$500,000 מהנכסים שלך. מערכת ההתרעה שלנו מציעה זיהוי מהיר פי 10 מבדיקות ידניות, ומבטיחה שלא תפספס איום.

מה כלול בתוצרים?

  • ניתוח דרישות ומודל איומים.
  • פיתוח חוזים חכמים ותרחישי ניטור.
  • שילוב עם ארנקים באמצעות Snaps ו-API.
  • פריסת תשתית (Tenderly, Alchemy).
  • תיעוד והדרכת משתמשים.
  • תמיכה טכנית למשך 3 חודשים.
  • גישה ללוחות מחוונים בזמן אמת ומערכות התראה.

לוח זמנים: 4 עד 8 שבועות. העלות מתחילה ב-$15,000 לשילוב בסיסי, עם רמות גבוהות יותר בהתאם למורכבות. הניסיון שלנו ב-Web3 (30+ פרויקטים, 10+ שילובי ארנקים) מבטיח הגנה אמינה מפני הונאות אישור.

הזמן ייעוץ לשילוב המערכת שלנו. צור קשר כדי לדון בפרויקט שלך. קבל גישת הדגמה למערכת והערך את יעילותה.