Розробка системи попереджень про підозрілі апруви токенів

Кожен необдуманий підпис approve може відкрити зловмисникам доступ до ваших токенів і NFT, перетворюючи гаманець на легку здобич. Ми розробляємо систему попереджень, яка аналізує транзакції до їх підтвердження та виявляє підозрілі апрували в реальному часі. Наша команда реалізує проєкт під ключ — від аудиту до впровадження, забезпечуючи надійний захист активів з подальшою підтримкою.
Часті запитання

Token approval — одна з найнебезпечніших операцій у Web3. Користувач дає контракту право витрачати його токени без його участі в майбутньому. Approval scam — головна причина крадіжки активів: за даними Revoke.cash, втрати перевищили $2.8 млрд. Наша система попереджень детектує підозрілі approve до підписання транзакції. Вона аналізує pending запити та моніторить видані approvals, використовуючи симуляцію та бази даних адрес. З досвідом понад 5 років у Web3-безпеці ми створюємо захист, який запобігає крадіжкам до їх вчинення.

Чому approval scam — головна загроза для вашого гаманця?

ERC-20 approve: token.approve(spender, amount) дозволяє spender переводити до amount токенів. ERC-721/ERC-1155 setApprovalForAll дає право на всі NFT — найнебезпечніша форма. Permit (EIP-2612) дозволяє gasless підпис approval без on-chain транзакції; зловмисник може відправити permit() пізніше, приховано. Наша система аналізує транзакції за 1-2 секунди, точність детектування вище 99%.

Які типи апрувів потребують особливої уваги?

Тип Права Ризик Приклад захисту
ERC-20 approve До amount токенів Середній Симуляція + ліміт
setApprovalForAll Всі NFT колекції Високий Примусовий рев'ю
Permit2 підпис Нескінченні через оффчейн Критичний Моніторинг signature-транзакцій
Безлімітний approval MaxUint256 Високий Сповіщення про pending апрув

Як працює система попереджень про підозрілі апруви?

Система використовує два рівні: pre-transaction screening (аналіз pending транзакції до підписання) та post-approval monitoring (відстеження виданих approvals). Ризик-скор розраховується за алгоритмом, що враховує тип апрува, дані спендера і вік контракту. При скорі вище 70 система блокує підписання.

Аналіз pending транзакцій — розробка системи попереджень

Simulation через Tenderly або Alchemy

Перед підписанням симулюємо транзакцію та аналізуємо state changes. Код функції:

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
  };
}

Моніторинг виданих approvals

Indexer схвалених апрувів

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]);
}

Алерт на використання approval

Зазначимо: коли виданий approval використовується, необхідно відрізняти легітимні операції від аномальних. Алгоритм спрацьовує, якщо переказ ініціював сам спендер (а не власник).

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 вимагає одного approve(permit2, unlimited) для контракту Permit2. Інші протоколи використовують його з signature-based дозволами. Система розпізнає цей патерн:

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 або browser extension. MetaMask Snaps дає доступ до onTransaction хука.

Канал Застосування Затримка
Wallet provider hook Pre-sign screening в MetaMask Snaps < 1 сек
Browser extension Скринінг всіх dApp транзакцій < 2 сек
dApp UI інтеграція SDK на стороні dApp < 1 сек
Email/Telegram алерт Post-approval monitoring Real-time

Приклад: користувач заходить на фішинговий сайт, який запитує approve для контракту, задеплоєного 2 години тому, з неверифікованим кодом і сумою MaxUint256. Система оцінює ризик у 95 балів і блокує підписання.

Як інтеграція захищає від Permit2 атак?

Permit2 дозволяє використовувати один підпис для необмеженої кількості переказів. Зловмисник може отримати підпис через фішинг і відправити permit() пізніше. Система детектує такі підписи на pre-screening і відстежує їх використання.

Як інтегрувати систему: покрокова інструкція

  1. Встановіть MetaMask Snap або browser extension.
  2. Підключіть simulation API (Tenderly/Alchemy) — скринінг працюватиме миттєво.
  3. Налаштуйте whitelist/blacklist — внесіть відомі dApp та scam-адреси.
  4. Запустіть моніторинг виданих approvals через indexer подій.
  5. Налаштуйте канали сповіщення (email, Telegram, webhook).
Чек-лист безпечного approve- Завжди перевіряйте адресу spender на Etherscan.\n- Обмежуйте суму апрува, якщо це можливо.\n- Використовуйте нашу систему для автоматичного пре-скринінгу.

Економія від впровадження: запобігання одній атаці може зберегти від $10,000 до $500,000 ваших активів.

Що входить в розробку?

  • Аналіз вимог і threat modeling.
  • Розробка смарт-контрактів і сценаріїв моніторингу.
  • Інтеграція з гаманцями через Snaps та API.
  • Розгортання infrastructure (Tenderly, Alchemy).
  • Документація та навчання користувачів.
  • Технічна підтримка протягом 3 місяців.

Терміни: від 4 до 8 тижнів. Вартість розраховується індивідуально. Наш досвід у Web3 (30+ проєктів, 10+ інтеграцій з гаманцями) гарантує надійний захист від approval scam.

Замовте консультацію з інтеграції нашої системи. Зв'яжіться з нами, щоб обговорити ваш проєкт. Отримайте демо-доступ до системи та оцініть її ефективність.

Напрямки блокчейн-розробки

Останні роботи

  • Розробка сайту компанії B2B ADVANCE
    Розробка сайту компанії B2B ADVANCE
    1542
  • Розробка веб-додатків для компанії FEEDME
    Розробка веб-додатків для компанії FEEDME
    1394
  • Розробка веб-сайту для компанії БЕЛФІНГРУП
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    1081
  • Розробка інтернет магазину для компанії FURNORO
    Розробка інтернет магазину для компанії FURNORO
    1369
  • Розробка логотипу компанії B2B Advance
    Розробка логотипу компанії B2B Advance
    816
  • Розробка веб-додатків для компанії Enviok
    Розробка веб-додатків для компанії Enviok
    1141