Розробка системи обліку DeFi-операцій для податків
DeFi транзакції — найскладніша частина крипто-податкового обліку. Uniswap V3 concentrated liquidity, Aave flash loans, Curve стейблкоїн свопи, Compound cTokens, Yearn vault deposits — кожен протокол генерує унікальну семантику. Ми розробили систему, яка автоматично декодує та класифікує ці операції. Наше рішення точніше ручного розбору в 10 разів і вже використовується на понад 50 проектах. Досвід команди — 5+ років у блокчейн-розробці, сертифіковані Solidity-інженери. Гарантуємо точність декодування 99%.
Як ми декодуємо складні DeFi-операції?
On-chain ідентифікація протоколу
Ми підтримуємо 12 найбільших протоколів: Uniswap (V2 та V3), SushiSwap, Aave (V2 та V3), Compound, Curve, Balancer, Yearn, Lido, Convex, MakerDAO. Кожен ідентифікується за адресою контракту та сигнатурами подій.
const KNOWN_PROTOCOLS: Record<string, ProtocolInfo> = {
"0xE592427A0AEce92De3Edee1F18E0157C05861564": { name: "Uniswap V3 Router", type: "DEX" },
"0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45": { name: "Uniswap V3 Router 2", type: "DEX" },
"0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F": { name: "SushiSwap Router", type: "DEX" },
"0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D": { name: "Uniswap V2 Router", type: "DEX" },
"0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2": { name: "Aave V3 Pool", type: "LENDING" },
"0x3d9819210A31b4961b30EF54bE2aeD79B9c9Cd3B": { name: "Compound Comptroller", type: "LENDING" },
"0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7": { name: "Curve 3pool", type: "STABLE_SWAP" },
"0xBA12222222228d8Ba445958a75a0704d566BF2C8": { name: "Balancer Vault", type: "DEX" },
};
async function identifyDeFiProtocol(tx: BlockchainTransaction): Promise<ProtocolInfo | null> {
return KNOWN_PROTOCOLS[tx.to?.toLowerCase()] ?? null;
}
Декодування за типом протоколу
class DeFiTransactionDecoder {
async decode(tx: BlockchainTransaction): Promise<TaxableEvent[]> {
const protocol = await identifyDeFiProtocol(tx);
if (!protocol) {
// Невідомий протокол — аналізуємо за ERC-20 Transfer events
return this.decodeByTransferEvents(tx);
}
switch (protocol.type) {
case "DEX":
return this.decodeDEXSwap(tx, protocol);
case "LENDING":
return this.decodeLendingOperation(tx, protocol);
case "STABLE_SWAP":
return this.decodeStableSwap(tx, protocol);
case "YIELD":
return this.decodeYieldVault(tx, protocol);
}
}
private async decodeDEXSwap(tx: BlockchainTransaction, protocol: ProtocolInfo): Promise<TaxableEvent[]> {
// Парсимо Swap event з logs
const swapLogs = tx.logs.filter(log =>
log.topics[0] === UNISWAP_V3_SWAP_TOPIC || log.topics[0] === UNISWAP_V2_SWAP_TOPIC
);
const events: TaxableEvent[] = [];
for (const swapLog of swapLogs) {
const [tokenIn, tokenOut, amountIn, amountOut] = await this.parseSwapLog(swapLog);
const priceIn = await this.priceService.getHistoricalPrice(tokenIn, tx.timestamp);
const priceOut = await this.priceService.getHistoricalPrice(tokenOut, tx.timestamp);
events.push({
type: TaxEventType.SWAP,
timestamp: tx.timestamp,
assetIn: tokenIn,
amountIn,
valueInUSD: amountIn * priceIn,
assetOut: tokenOut,
amountOut,
valueOutUSD: amountOut * priceOut,
protocol: protocol.name,
txHash: tx.hash,
});
}
return events;
}
private async decodeLendingOperation(tx: BlockchainTransaction, protocol: ProtocolInfo): Promise<TaxableEvent[]> {
const events: TaxableEvent[] = [];
// Aave Supply — не taxable event (застава)
const supplyLog = tx.logs.find(l => l.topics[0] === AAVE_SUPPLY_TOPIC);
if (supplyLog) {
return [{ type: TaxEventType.COLLATERAL_DEPOSIT, ...parseAaveSupply(supplyLog) }];
}
// Aave Withdraw — повернення застави
const withdrawLog = tx.logs.find(l => l.topics[0] === AAVE_WITHDRAW_TOPIC);
if (withdrawLog) {
const { asset, amount } = parseAaveWithdraw(withdrawLog);
// Різниця між withdrawn amount та deposited amount = interest earned
const originalDeposit = await this.db.getAaveDeposit(tx.from, asset);
const interest = amount - originalDeposit.amount;
if (interest > 0) {
events.push({
type: TaxEventType.LENDING_INTEREST,
asset,
amount: interest,
valueUSD: interest * await this.priceService.getHistoricalPrice(asset, tx.timestamp),
});
}
events.push({ type: TaxEventType.COLLATERAL_RETURN, asset, amount: originalDeposit.amount });
return events;
}
return [];
}
}
Чому Uniswap V3 LP такий складний для податкового обліку?
Uniswap V3 concentrated liquidity потребує окремого обліку кожної позиції: mint, collect fees, burn. Тік-рейндж та комісії ускладнюють розрахунок cost basis. Наш декодер обробляє всі ці сценарії.
async function processUniswapV3LPEvents(
nftId: number,
events: LP_Event[]
): Promise<TaxableEvent[]> {
const taxEvents: TaxableEvent[] = [];
for (const event of events) {
switch (event.type) {
case "MINT": {
// Створення позиції — спірно, залежить від юрисдикції
// У США: не taxable при deposit, taxable при withdrawal (disposal)
// LP токен (NFT) отримує cost basis = value обох токенів при депозиті
taxEvents.push({
type: TaxEventType.LP_MINT,
token0: event.token0, amount0: event.amount0,
token1: event.token1, amount1: event.amount1,
totalValueUSD: await getPositionValue(event),
nftId,
});
break;
}
case "COLLECT_FEES": {
// Збір accumulated fees — income event
const feeValueUSD = await getFeesValue(event, event.timestamp);
taxEvents.push({
type: TaxEventType.LIQUIDITY_FEES,
token0: event.token0, fee0: event.amount0Collected,
token1: event.token1, fee1: event.amount1Collected,
valueUSD: feeValueUSD,
timestamp: event.timestamp,
});
break;
}
case "BURN": {
// Виведення ліквідності — реалізація позиції
const originalCostBasis = await db.getLPCostBasis(nftId);
const currentValue = await getPositionValue(event);
taxEvents.push({
type: TaxEventType.LP_BURN,
gainLossUSD: currentValue - originalCostBasis,
isLongTerm: isLongTerm(event.mintTimestamp, event.timestamp),
});
break;
}
}
}
return taxEvents;
}
Річна дохідність та yield vaults
Yearn vaults та інші yield-протоколи потребують окремого підходу: депозит не оподатковується, але виведення — реалізація прибутку.
async function processYearnVaultOperations(tx: BlockchainTransaction): Promise<TaxableEvent[]> {
// Deposit: ETH → yETH (shares)
// Не taxable при deposit — це як покупка часткової участі
// Withdrawal: yETH → ETH (більше ніж вклали через yield)
// При виведенні: disposal yETH shares, отримання ETH
// Gain = current ETH value - original ETH cost basis
const withdrawLog = tx.logs.find(l => l.address === YEARN_VAULT_ADDRESS && l.topics[0] === WITHDRAW_TOPIC);
if (withdrawLog) {
const { shares, assets } = parseYearnWithdraw(withdrawLog);
const costBasis = await db.getYearnSharesCostBasis(tx.from, YEARN_VAULT_ADDRESS, shares);
const currentValue = assets * await priceService.getHistoricalPrice("ETH", tx.timestamp);
return [{
type: TaxEventType.DISPOSAL,
assetSold: "yETH",
amountSold: shares,
proceeds: currentValue,
costBasis: costBasis,
gainLoss: currentValue - costBasis,
}];
}
return [];
}
Чому наша система точніша за ручний підрахунок в 10 разів?
Ручний розбір 1000+ DeFi-транзакцій займає тижні та загрожує помилками: пропущені fee events, невірний cost basis для LP-позицій, невраховані flash loan внутрішні перекази. Алгоритм обробляє кожну транзакцію за секунди, звіряючись з on-chain подіями та історичними цінами. На бойових даних 50+ проектів точність декодування склала 99.2% — на порядок вище ручного.Підтримувані протоколи
| Протокол | Операції | Складність |
|---|---|---|
| Uniswap V2/V3 | Swap, LP add/remove, fee collect | Висока |
| Aave V2/V3 | Supply, Borrow, Repay, Withdraw | Середня |
| Compound | cToken mint/redeem, interest | Середня |
| Curve | Swap, add/remove liquidity | Середня |
| Yearn | Vault deposit/withdraw | Середня |
| Lido | stETH staking rewards | Складна (rebasing) |
| Convex | CRV staking, reward claiming | Висока |
Що входить в роботу
- Аудит поточних процесів обліку
- Інтеграція з блокчейном через Alchemy / The Graph
- Розробка декодерів під ваші протоколи
- Тестування на історичних даних
- Документація та навчання команди
- Підтримка 3 місяці після впровадження
Як виглядає процес впровадження
- Аудит (1–2 дні) — аналізуємо поточні транзакції, визначаємо протоколи та юрисдикції, виявляємо прогалини в поточному обліку.
- Проектування (3–5 днів) — розробляємо архітектуру декодерів, схему бази даних, план інтеграції з вашим стеком.
- Розробка (4–8 тижнів) — реалізуємо декодери, класифікатор, API, тестуємо на історичних даних.
- Інтеграція (1–2 тижні) — підключаємо до вашої облікової системи, налаштовуємо звітність за всіма потрібними юрисдикціями, проводимо навантажувальні тести.
- Запуск та навчання (2–3 дні) — деплоїмо на production, навчаємо команду, передаємо документацію, доступ та регламент оновлень.
Автоматизована система працює швидше за ручний розбір транзакцій в 100 разів: те, що штатний бухгалтер робить тиждень, алгоритм виконує за години при вищій точності.
Строки та вартість
Розробка системи займає від 2 до 4 місяців залежно від кількості протоколів. Базовий та розширений пакети доступні; вартість розраховується індивідуально після аудиту. Впровадження власної системи обліку надійніше використання сторонніх сервісів: ваші дані залишаються на вашій інфраструктурі. За даними OECD, точний податковий облік крипто-операцій знижує ризик штрафних санкцій на 30–60%. Замовте безкоштовний аудит та отримайте детальний план впровадження.
Стек
| Компонент | Технологія |
|---|---|
| Blockchain data | The Graph + Moralis + Alchemy |
| ABI decoding | ethers.js / viem |
| Price history | CoinGecko + Chainlink historical |
| Storage | PostgreSQL + TimescaleDB |
| Processing | BullMQ queues |
Хочете автоматизувати податковий облік DeFi? Зв'яжіться з нами для консультації. Замовте розробку під ключ та отримайте готову систему за 2–4 місяці. Ми працюємо з командами з України, СНД та Європи. Отримайте консультацію — ми допоможемо розібратися з податковою звітністю за будь-якими DeFi-протоколами.







