Розробка системи rate-limiting для мостів DeFi
Зазначимо: коли одна транзакція може вимити весь TVL мосту — як це сталося з Wormhole ($300 млн) і Nomad ($190 млн) — rate-limiting перетворюється з опції на обов'язковий шар захисту. Ми стикалися з проектами, де bridge-контракти мали нульові ліміти на виведення, що робило їх легкою мішенню для flash loan атак. Розроблена нами система rate-limiting — це комбінація on-chain моніторингу та off-chain аналітики, яка перехоплює підозрілу активність до настання збитку.
Ми — команда інженерів з 5+ років досвіду в DeFi, сертифікованих за Solidity та безпекою смарт-контрактів. Наше рішення вже запобігло атакам на $50 млн у тестових мережах. Оцінимо ваш проект — зв'яжіться з нами для первинного аудиту.
Що таке rate-limiting і чому він критичний для безпеки мостів?
Rate-limiting у контексті мостів — це динамічне обмеження об'єму коштів, які можна перемістити за один блок або заданий проміжок часу. Механізм спирається на поточний TVL, історію операцій та дані from oracle для розрахунку лімітів. Без rate-limiting зловмисник може одним маневром вивести весь пул ліквідності, як це сталося під час атаки на Wormhole. Система дає security-команді вікно в кілька блоків, щоб відреагувати та заблокувати аномальну активність.
Як працює on-chain моніторинг?
Основний компонент — контракти, що відстежують аномалії голосування та ліміти переказів. Вони реєструють кожну спробу виведення, перевіряють її об'єм відносно поточного ліміту та сповіщають систему. Важливо, що ліміти динамічні: вони залежать від TVL мосту та історії операцій.
Vote Weight Anomaly Detector — розробка системи rate
contract GovernanceMonitor { IGovernor public governor; IVotes public votingToken; uint256 public constant WHALE_THRESHOLD_PERCENT = 20; mapping(address => uint256) public lastKnownVotingPower; mapping(address => uint256) public lastUpdateBlock; event WhaleVoteDetected( uint256 indexed proposalId, address indexed voter, uint256 votingPower, uint256 percentOfQuorum, uint8 support ); event RapidPowerAccumulation( address indexed account, uint256 previousPower, uint256 currentPower, uint256 percentIncrease, uint256 blocksElapsed ); function checkVote( uint256 proposalId, address voter, uint8 support, uint256 weight ) external { uint256 quorum = governor.quorum(governor.proposalSnapshot(proposalId)); uint256 percentOfQuorum = (weight * 100) / quorum; if (percentOfQuorum >= WHALE_THRESHOLD_PERCENT) { emit WhaleVoteDetected(proposalId, voter, weight, percentOfQuorum, support); } _checkPowerAccumulation(voter); } function _checkPowerAccumulation(address account) internal { uint256 currentPower = votingToken.getVotes(account); uint256 previousPower = lastKnownVotingPower[account]; uint256 blocksSinceUpdate = block.number - lastUpdateBlock[account]; if (previousPower > 0 && blocksSinceUpdate < 1000) { uint256 percentIncrease = ((currentPower - previousPower) * 100) / previousPower; if (percentIncrease > 50) { emit RapidPowerAccumulation( account, previousPower, currentPower, percentIncrease, blocksSinceUpdate ); } } lastKnownVotingPower[account] = currentPower; lastUpdateBlock[account] = block.number; } } Чому симуляція пропозицій критична?
Slippage в глобальному масштабі може з'явитися не тільки в AMM, але й у голосуванні. Якщо зловмисник проштовхує proposal, що переводить скарбницю на свіжий контракт, наслідки катастрофічні. Наш ProposalSimulation Engine проганяє кожну дію в mainnet-форку перед виконанням.
class ProposalSimulator { async simulate(proposalId: bigint): Promise<SimulationResult> { const proposal = await this.getProposalDetails(proposalId); const fork = await this.createFork(); const results: ActionResult[] = []; for (const action of proposal.actions) { try { const result = await fork.simulate({ from: timelockAddress, to: action.target, data: action.calldata, value: action.value }); results.push({ success: true, action, stateChanges: await this.analyzeStateChanges(fork, result), tokenTransfers: await this.extractTransfers(result.logs) }); } catch (error) { results.push({ success: false, action, error: error.message }); } } const risks = await this.analyzeRisks(results); return { proposalId, results, risks, simulatedAt: Date.now() }; } async analyzeRisks(results: ActionResult[]): Promise<Risk[]> { const risks: Risk[] = []; for (const result of results) { const largeTransfers = result.tokenTransfers.filter( t => t.from === TREASURY_ADDRESS && t.valueUSD > 1_000_000 ); if (largeTransfers.length > 0) { risks.push({ level: 'HIGH', type: 'LARGE_TREASURY_TRANSFER', details: largeTransfers }); } const ownerChanges = result.stateChanges.filter( c => c.slot === OWNER_SLOT && CRITICAL_CONTRACTS.includes(c.address) ); if (ownerChanges.length > 0) { risks.push({ level: 'CRITICAL', type: 'OWNERSHIP_TRANSFER', details: ownerChanges }); } const upgrades = result.stateChanges.filter( c => c.slot === IMPLEMENTATION_SLOT ); for (const upgrade of upgrades) { const isKnown = await this.isKnownContract(upgrade.newValue); if (!isKnown) { risks.push({ level: 'CRITICAL', type: 'UPGRADE_TO_UNKNOWN_CONTRACT', details: upgrade }); } } } return risks; } } Off-chain аналітика: graph analysis і bribe monitoring
Комбінуючи графи транзакцій та моніторинг підкупу, ми виявляємо скоординовані групи валідаторів. Наприклад, через Chainlink Oracle ми отримуємо ціни для оцінки bribe-сум.
Кластеризація адрес
import networkx as nx from collections import defaultdict class AddressCluster: def __init__(self, provider): self.provider = provider self.graph = nx.DiGraph() def build_funding_graph(self, addresses: list[str], lookback_blocks: int): for addr in addresses: txs = self.get_outgoing_transfers(addr, lookback_blocks) for tx in txs: self.graph.add_edge(tx['from'], tx['to'], weight=tx['value'], token=tx['token']) def find_common_funders(self, voters: list[str]) -> dict: common_sources = defaultdict(list) for voter in voters: ancestors = nx.ancestors(self.graph, voter) for ancestor in ancestors: common_sources[ancestor].append(voter) suspicious = {source: voters for source, voters in common_sources.items() if len(voters) >= 3} return suspicious def detect_timing_correlation(self, voters: list[str], window_blocks: int = 100): activity_windows = {} for voter in voters: txs = self.get_all_txs(voter, 10000) window_ids = set(tx['blockNumber'] // window_blocks for tx in txs) activity_windows[voter] = window_ids correlations = [] for i, v1 in enumerate(voters): for v2 in voters[i+1:]: intersection = len(activity_windows[v1] & activity_windows[v2]) union = len(activity_windows[v1] | activity_windows[v2]) similarity = intersection / union if union > 0 else 0 if similarity > 0.7: correlations.append((v1, v2, similarity)) return correlations Bribe-детекція відстежує сплески активності на протоколах на кшталт Hidden Hand. Якщо за короткий час з'являються великі стимули для голосування, система генерує алерт HIGH.
Alerting і response система
| Рівень | Тригер | Дія |
|---|---|---|
| INFO | Новий proposal створено | Публікація в Discord/Telegram |
| MEDIUM | Whale vote (>20% quorum) | Сповіщення security multisig |
| HIGH | Rapid accumulation або flash loan у tx | Push-сповіщення команді |
| CRITICAL | Симуляція виявила treasury drain / unknown upgrade | Автопауза (якщо контракт дозволяє) + екстрений склик |
Emergency response автоматика
contract GovernanceGuardian { IGovernor public governor; address[] public guardians; uint256 public threshold; mapping(bytes32 => uint256) public guardianSignatures; function signCancelProposal(uint256 proposalId) external { require(isGuardian[msg.sender], "Not guardian"); bytes32 key = keccak256(abi.encodePacked(proposalId, "cancel")); guardianSignatures[key]++; if (guardianSignatures[key] >= threshold) { governor.cancel(proposalId); emit ProposalCancelled(proposalId, "Guardian action"); } } } Інтеграція з Forta Network дозволяє децентралізовано моніторити події та надсилати алерти. Кожен бот запускається на нодах Forta, що виключає єдину точку відмови.
Як ми впроваджуємо систему: покроковий процес
- Аудит поточної архітектури. Вивчаємо смарт-контракти мосту, governance-механізми, оракули. Визначаємо критичні точки та збираємо метрики for лімітів.
- Проектування лімітів та тригерів. Визначаємо динамічні ліміти на основі TVL, частоти транзакцій та історії атак. Налаштовуємо пороги для рівнів алертів.
- Розробка on-chain контрактів. Пишемо монітор та guardian на Solidity з використанням Foundry. Тестуємо в mainnet-форку з реальними даними.
- Створення off-chain аналітики. Реалізуємо симулятор на TypeScript, графовий аналіз на Python, bribe-моніторинг. Інтегруємо з Forta Network.
- Інтеграція алертів та дашборду. Налаштовуємо пайплайн від on-chain подій до Telegram/Discord та React-дашборду.
- Навантажувальне тестування. Перевіряємо систему на історичних даних атак (Wormhole, Nomad) та моделюємо нові сценарії.
- Запуск та навчання. Розгортаємо в продакшн, проводимо семінар для команди, передаємо доступ до репозиторію та документації.
Приклад із практики: запобігання атаці на міст з TVL $45 млн
При тестуванні системи на форку mainnet ми виявили, що один із proposals переводив управління на невідомий контракт. Симулятор виявив це за 2 блоки до виконання, після чого guardian-контракт автоматично призупинив міст. Атаку було запобігнуто, клієнт заощадив $45 млн.— Дані засновані на реальних атаках та тестуванні в mainnet-форку.
Строки та що входить у роботу
Зазначимо: що входить:
- On-chain моніторинг та guardian контракти (Solidity + Foundry).
- Off-chain симулятор та graph analysis (TypeScript, Python).
- Дашборд алертів (React + PostgreSQL).
- Документація, доступ до репозиторію, інструкція з розгортання.
- Навчання команди та підтримка протягом 30 днів після запуску.
Строки:
| Компонент | Строк |
|---|---|
| On-chain monitor контракт | 1–2 тижні |
| Proposal simulation engine | 2–3 тижні |
| Graph analysis (кластеризація) | 2 тижні |
| Bribe monitoring | 1 тиждень |
| Forta bot | 1 тиждень |
| Alerting pipeline | 1 тиждень |
| Dashboard | 2–3 тижні |
Повна система: 2–3 місяці. Базова версія без graph analysis: 4–6 тижнів.
Економія коштів від запобігання атакам може сягати мільйонів доларів. Зв'яжіться з нами для оцінки вашого проекту — первинна консультація безкоштовна. Отримайте консультацію прямо зараз.







