
Маркет-мейкинг требует баланса между предоставлением ликвидности и защитой капитала. ADAMANT mm bot позволяет эмитентам токенов и биржам создавать динамическую ликвидность и торговые объемы контролируемым, автоматизированным способом. Однако по мере развития рынков развиваются и противники.
Issue #93 представил ключевое оборонительное обновление: Sniper Bot Watcher. Оно устраняет структурную уязвимость, затрагивающую почти все стратегии автоматического маркет-мейкинга — эксплуатацию со стороны сверхбыстрых внешних ботов.
Уязвимость автоматического маркет-мейкинга
Боты маркет-мейкинга часто генерируют объем и поддерживают спред, размещая ордера с обеих сторон стакана. Один из распространённых механизмов — внутреннее сопоставление: бот размещает ордер маркера внутри спреда, а затем спустя короткое время размещает соответствующий ордер тейкера для его исполнения, создавая легитимную торговую активность при сохранении баланса инвентаря.
Проблема заключается в неизбежной задержке между этими двумя шагами. Даже если она крайне мала, она существует, а в современных электронных рынках миллисекунды имеют значение. Внешние высокоскоростные боты в реальном времени отслеживают стаканы ордеров и мгновенно реагируют при появлении новой ликвидности. Как только бот маркет-мейкинга публикует свой ордер маркера, эти боты перехватывают его до того, как приходит внутренний ордер сопоставления.
Возникают два основных типа эксплуатации. В первом случае третья сторона немедленно исполняет ордер Покупки, оставляя последующий ордер Продажи неисполненным или частично исполненным, и бот теряет USDT. Во втором случае третья сторона размещает ордер Покупки выше ордера бота, и ордер Продажи бота исполняется с этой стороной, в результате чего бот теряет TOKEN. Результатом становятся не редкие потери, а систематическая эксплуатация.
Почему традиционные методы защиты недостаточны
Может показаться, что можно устранить задержку или скорректировать время исполнения. На практике это невозможно. API бирж имеют задержки, сетевая передача данных занимает время, и даже самая быстрая инфраструктура не может гарантировать атомарное размещение и исполнение ордеров во внешних системах. Увеличение задержек облегчает эксплуатацию; их сокращение помогает, но не устраняет разрыв полностью. Рандомизация времени исполнения вносит непредсказуемость, но боты-снайперы адаптивны и анализируют паттерны со временем.
Необходимо не более быстрое исполнение, а интеллектуальное обнаружение и реакция.
Представляем Sniper Bot Watcher
Sniper Bot Watcher — это слой обнаружения и смягчения угроз, интегрированный в ADAMANT mm bot. Его задача — не запрещать торговлю, а отслеживать поведенческие паттерны и выявлять, когда внешние боты эксплуатируют систему. При обнаружении подозрительной активности бот может защитно реагировать: изменять поведение исполнения, приостанавливать торговые стратегии, корректировать логику размещения ордеров или активировать защитные режимы, предназначенные для снижения рисков.
Следующий код демонстрирует обнаружение активности бота-снайпера:
} else if (order1Status === 'filled' && order2Status === 'filled') {
log.info('Trader: Both maker and taker executeInSpread t-orders are self-filled.');
order.update({
coin1AmountFilled: coin1Amount,
coin2AmountFilled: coin2Amount,
isExecuted: true,
});
} else if (order1Status === 'filled' && ['new', 'part_filled'].includes(order2Status)) {
// Scenario1: After maker order is placed in spread, a third party bot quickly takes it, and the taker order remains unfilled or partially filled
sniperBotActivity(1, order2Details, coin1Amount);
await addFillsDbRecord(order2Details, order, false); // Maker order is partially or fully filled by a sniper bot
order.update({
coin1AmountFilled: order2Details.amountExecuted, // Self-filled amount, excluding sniper bot fills
coin2AmountFilled: order2Details.volumeExecuted,
isExecuted: false, // Not fully executed
});
}
Когда количество вмешательств превышает пороговое значение, бот переходит в Безопасный режим:
/**
* Records a sniper-bot intervention for a given scenario.
* Triggers safe mode when the total interventions reach the threshold.
* @param {number} scenario Scenario index: 1 or 2
* @param {OrderInfoResult} orderDetails Exchange order details (e.g., order2Details), for logging only
* @param {number} coin1Amount Order amount in base coin, for logging only
* @returns {void}
*/
function sniperBotActivity(scenario, orderDetails, coin1Amount) {
sbwActivityCounters[scenario]++;
const fillPercent = (orderDetails.amountExecuted / coin1Amount * 100).toFixed(2);
log.warn(`Trader: While the maker t-order is filled, the taker is ${orderDetails.status} (${fillPercent}% self-filled). This may be Scenario ${scenario} of third-party bot intervention; incrementing the counters to ${sbwActivityTotalString()} (Safe mode threshold: ${sbwEnabled ? safeModeThreshold : 'Disabled'}).`);
if (sbwEnabled && sbwActivityTotal() >= safeModeThreshold) {
sniperBotSafeMode();
resetSniperBotCounters();
}
}